หากคุณเป็นวิศวกรหรือนักพัฒนาที่มาจากภาษาการเขียนโปรแกรมต่างกัน คุณอาจเคยใช้วิธีดั้งเดิมที่เรียกว่า 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