หากคุณเป็นวิศวกรหรือนักพัฒนาที่มาจากภาษาการเขียนโปรแกรมต่างกัน คุณอาจเคยใช้วิธีดั้งเดิมที่เรียกว่า sleep() เพื่อหยุดหรือหยุดการทำงานของเมธอดชั่วคราว JavaScript ไม่มีวิธีการดั้งเดิมดังกล่าว
ในบทความนี้ เราจะพูดถึงสองวิธีที่ต่างกันที่เราสามารถใช้ JavaScript เพื่อจำลองฟังก์ชัน sleep:Promises และ async/await functions
บทนำเกี่ยวกับฟังก์ชันอะซิงโครนัส
เราไม่ควรพูดถึง Promises หรือฟังก์ชัน async/await ใน JavaScript โดยไม่พูดถึง setTimeout() ก่อน วิธีการสั้น ๆ วิธีนี้จะแสดงให้เห็นว่าเหตุใดจึงต้องมีการทำสัญญาใน JavaScript
จาวาสคริปต์เป็นแบบเธรดเดียว
เมื่อเราพูดว่า JavaScript เป็นภาษาเธรดเดียว สิ่งที่เราหมายถึงคือ JavaScript มี call stack เดียวเท่านั้นและหนึ่ง memory heap ในระดับสูง นี่หมายความว่า JavaScript อ่านโค้ด ทีละบรรทัดตามลำดับ และต้องรันโค้ดก่อนที่จะย้ายไปยังบรรทัดถัดไป สิ่งนี้ทำให้ JavaScript ซิงโครนัสโดยธรรมชาติ บางครั้ง เราต้องแก้ไขเพื่อให้โค้ดของเราไม่ตรงกัน
โค้ดซิงโครนัสกับโค้ดอะซิงโครนัส
ลองดูตัวอย่างนี้
//synchronous
console.log("This will print first")
console.log("This will print second")
console.log("This will print third");
ค่อนข้างตรงไปตรงมาใช่ไหม console.logs แต่ละรายการจะพิมพ์ต่อเนื่องกันเนื่องจาก JavaScript ดำเนินการตามลำดับ
สมมติว่าเราต้องการพิมพ์บรรทัดที่สองก่อนบรรทัดที่สาม เราจะพิมพ์ console.log . นั้นได้อย่างไร ออกจากเทิร์น? เราสามารถทำได้ด้วย setTimeout() :
//setTimeout
console.log("This will print first")
setTimeout(() => {
console.log("This will print third")
}, 1000);
console.log("This will print second");
setTimeout() ช่วยให้เราสามารถเรียกใช้ฟังก์ชัน JavaScript โดยไม่ต้องบล็อกเธรดเพื่อให้โค้ดอื่นสามารถเรียกใช้ได้ อาร์กิวเมนต์แรกคือฟังก์ชันเรียกกลับที่ทำงานหลังจากระยะเวลาที่กำหนด (อาร์กิวเมนต์ที่สอง) อาร์กิวเมนต์ที่สองจะแสดงเป็นหน่วยมิลลิวินาที
81% ของผู้เข้าร่วมกล่าวว่าพวกเขารู้สึกมั่นใจมากขึ้นเกี่ยวกับโอกาสในการทำงานด้านเทคโนโลยีหลังจากเข้าร่วม bootcamp จับคู่กับ Bootcamp วันนี้
ผู้สำเร็จการศึกษาจากหลักสูตร bootcamp โดยเฉลี่ยใช้เวลาน้อยกว่าหกเดือนในการเปลี่ยนอาชีพ ตั้งแต่เริ่มต้น bootcamp ไปจนถึงหางานแรก
setTimeout()นี้ setTimeout() method เลียนแบบวิธีการนอนที่เป็นภาษาอื่นโดย:
- การตั้งค่าตัวจับเวลาในพื้นหลังเมื่อกลไก JavaScript เรียกใช้
setTimeout()ฟังก์ชัน - เรียกใช้โค้ดอื่นต่อไปในขณะที่ตัวจับเวลานับถอยหลัง
- เรียกใช้ฟังก์ชันเรียกกลับใน
setTimeout()เมื่อตัวจับเวลาถึงศูนย์
ทำความเข้าใจว่า setTimeout() งานมีความสำคัญอย่างยิ่งในการทำความเข้าใจว่า Promises และ async/await Functions ทำงานอย่างไร เราจะพูดถึงเรื่อง Promis ต่อไป
สัญญา
สร้างสัญญา
คำมั่นสัญญาเป็นวิธีดำเนินการตรรกะแบบอะซิงโครนัส คอนสตรัคเตอร์ Promise ใช้ฟังก์ชันเรียกกลับที่มีสองพารามิเตอร์:แก้ไขและปฏิเสธ ฟังก์ชันเรียกกลับนี้มีตรรกะที่เมื่อเสร็จแล้วจะเรียกใช้ฟังก์ชันแก้ไขหรือปฏิเสธโดยมีการตอบกลับ
console.log("before promise")
let promise = new Promise((resolve, reject) => {
let resolvedFlag = false;
//this is just a flag so we can intentionally throw the response to test logic
console.log("first");
console.log("second")
console.log("third")
console.log("fourth");
resolvedFlag = true; //flip resolved to true once all console logs are done
if(resolvedFlag) { //if resolved is true invoke the resolve function
resolve("Promise resolved");
console.log("after promise");
} else { // else invoke the reject function with a new Error object with message
reject(new Error("Promise failed"));
console.log("after promise");
}
});
ข้อมูลโค้ดที่นี่แสดงให้เห็นถึงสัญญาง่ายๆ คำสัญญาสามารถอยู่ในสามสถานะ:
รอดำเนินการ – ไม่มีการแก้ไขหรือปฏิเสธ – นี่คือสถานะเริ่มต้นของสัญญา
แก้ไขแล้ว – ดำเนินการสำเร็จ
ปฏิเสธ – ข้อผิดพลาดในการดำเนินการ
ลองสลับค่าสถานะการแก้ปัญหาจากจริงเป็นเท็จในข้อมูลโค้ดด้านบนเพื่อแสดงวิธีแก้ปัญหาของคำสัญญาที่แก้ไขแล้วและคำสัญญาที่ถูกปฏิเสธ
สิ่งสำคัญที่ต้องจำไว้คือ Promise นี้มีฟังก์ชันที่หยุดการทำงานของสคริปต์ชั่วคราวจนกว่า Promise จะได้รับการแก้ไขหรือปฏิเสธ จากนั้นสคริปต์จะกลับมาทำงานต่อ
การใช้การตอบกลับตามสัญญา
เมื่อเราเริ่มต้นอินสแตนซ์ของ Promise เราจะใช้ then() และ catch() เพื่อจัดวางตรรกะที่เราต้องการใช้หลังจากที่เราได้รับการตอบสนองจาก Promise ที่ส่งคืน นี้จัดวางเป็นหนึ่งคำสั่ง – ภาพรวมระดับสูงดูเหมือนว่า:
promise.then(func).catch(func);
ในวงเล็บที่เรียกใช้เมธอด then และ catch เป็นฟังก์ชันที่ไม่ระบุตัวตนที่มีการตอบกลับเป็นพารามิเตอร์
promise // the promise we created above in prev code snippet.
.then(response => { // hits here if successful response
// the logic that happens on successful response
console.log(response);
console.log("after promise");
})
.catch(error => { // catches any errors here.
// the logic that happens on error response
console.log(error.message);
console.log("after promise");
}) สัญญามักใช้เมื่อโทรไปยังฐานข้อมูลหรือเมื่อทำการร้องขอ HTTP
ฟังก์ชัน Async/Await
วิธีสุดท้ายที่เราสามารถจำลอง sleep() เมธอดคือการใช้ฟังก์ชัน async/await โดยพื้นฐานแล้ว ฟังก์ชันอะซิงโครนัสเหล่านี้เป็นอีกวิธีหนึ่งในการสร้างตรรกะเดียวกันกับที่เราจะใช้ใน Promises แต่มีโค้ดน้อยกว่า
คำว่า async ถูกวางไว้หน้า ฟังก์ชัน คีย์เวิร์ดในฟังก์ชันก่อน ES6 และก่อนพารามิเตอร์ในฟังก์ชัน ES6+ ตรรกะใด ๆ ที่คุณต้องการให้เสร็จสิ้นก่อนที่จะดำเนินการต่อไปในบล็อกของรหัสนี้
const firstFunction = () => { // logic that you want to have done asynchronously
let resolved = true;
if(resolved) {
let respObj = { message: "Resolved!"};
return respObj.message;
} else {
let errObj = { message: "Error!"};
return errObj.message;
}
}
const asyncExample = async () => {
// async keyword before where parameters would go
console.log("Calling function...");
let result = await firstFunction();
// await goes before the invocation of the function that contains your logic.
// won't go to the next line until the function is done.
console.log(result);
return result;
}
asyncExample() // invokes the async/await function การใช้ฟังก์ชัน async/await ส่งผลให้เกิดกระบวนการตามสัญญาแบบอะซิงโครนัสที่เหมือนกัน แต่มีโค้ดน้อยกว่า
บทสรุป
ในบทความนี้ เรามาดูวิธีเลียนแบบ sleep() ฟังก์ชันที่เป็นของภาษาโปรแกรมอื่นๆ เราใช้ setTimeout() เพื่อแสดงแนวคิดของฟังก์ชัน JavaScript แบบอะซิงโครนัสเพื่อให้เราสามารถดูที่ Promises และฟังก์ชัน async/await