ไบนารีข้อมูล
เนื้อหาทั้งหมดในคอมพิวเตอร์: ข้อความ ตัวเลข รูปภาพ เสียง และวิดีโอ จะถูกแสดงด้วยไบนารี่ในที่สุด
JS
สามารถประมวลผลข้อมูลที่ใช้งานง่ายได้โดยตรง เช่น สตริง โดยปกติแล้วเราจะแสดงเนื้อหาเหล่านี้แก่ผู้ใช้
แต่คุณอาจคิดว่า JS It ยังสามารถประมวลผลรูปภาพได้
JS
หรือ HTML
มักจะประมวลผลรูปภาพไปยังเบราว์เซอร์utf-8
GBK
ต่างกันสำหรับเซิร์ฟเวอร์
sharp
ใน Node ซึ่งมีหน้าที่ในการอ่านรูปภาพหรือ Buffer
ของรูปภาพที่เข้ามาแล้วประมวลผลNode
การเชื่อมต่อแบบยาวจะถูกสร้างขึ้นผ่าน TCP
TCP จะส่งไบต์ เราจำเป็นต้องแปลงข้อมูลเป็นไบต์ก่อนที่จะส่งผ่านและต้องทราบขนาดของไบต์ที่ส่ง (ลูกค้าต้องตัดสินว่าจะอ่านเนื้อหาได้มากน้อยเพียงใดตามขนาด)Buffer และ Binary
เราจะพบว่า สำหรับการพัฒนาส่วนหน้านั้นมักจะไม่ค่อยเกี่ยวข้องกับการจัดการไบนารี่ซึ่งกันและกัน แต่สำหรับฝั่งเซิร์ฟเวอร์เพื่อที่จะใช้งานฟังก์ชั่นต่างๆ มากมาย เราจะต้องดำเนินการข้อมูลไบนารี่โดยตรง
ดังนั้นเพื่ออำนวยความสะดวกให้กับนักพัฒนาในการทำหน้าที่ให้สมบูรณ์มากขึ้น , Node
ได้จัดเตรียมคลาสชื่อ Buffer
ให้กับเรา และเป็นคลาสแบบโกลบอล อย่างที่
เราเคยบอกไปแล้วว่าข้อมูลไบนารี่ถูกจัดเก็บไว้ใน Buffer แล้วมันจะถูกเก็บไว้อย่างไร?
8
บิตได้: 00000000
ซึ่งก็คือหนึ่งไบต์พอดีเพราะเหตุใดจึงเป็น 8 บิต
1 byte = 8 bit
byte
แล้ว 8 บิตจะรวมกันเป็นหน่วยหนึ่ง1 byte = 8 bit
, 1kb = 1024 byte
, 1M = 1024kb
, 1 G = 1024 M
int
ในภาษาการเขียนโปรแกรมหลายภาษาคือ 4
ไบต์ และชนิด long
คือ 8
ไบต์TCP
ส่งRGB
คือ 255
ตามลำดับ ดังนั้นโดยพื้นฐานแล้วบัฟเฟอร์และสตริง
Buffer
จะถูกเก็บไว้หนึ่งไบต์ในคอมพิวเตอร์ซึ่งก็คือ เทียบเท่ากับอาร์เรย์ของไบต์ แต่ละรายการในอาร์เรย์มีขนาดหนึ่งไบต์
หากเราต้องการใส่สตริงลงในบัฟเฟอร์ กระบวนการคืออะไร?
buffer
ซ์บัฟเฟอร์ที่มีลักษณะเฉพาะ
// ใช้คีย์เวิร์ดใหม่เพื่อสร้างอินสแตนซ์บัฟเฟอร์ แต่วิธีการสร้างนี้หมดอายุแล้ว const buffer = new Buffer(ข้อความ) console.log(บัฟเฟอร์); // <บัฟเฟอร์ 48 65 6c 6c 6f> console.log(buffer.toString()); // สวัสดี
การเข้ารหัสและถอดรหัสสตริงภาษาจีน
buffer
ต้นคือ utf-8
ดังนั้นในโค้ดต่อไปนี้ คลาส Buffer
จึงใช้การเข้ารหัส utf-8 เพื่อเข้ารหัสสตริงของเรา เรายังใช้ utf-8 เพื่อถอดรหัสสตริง3
ข้อความ const การเข้ารหัสไบนารี่ 3 ไบต์ = 'Hello' // ใช้ Buffer.from เพื่อถอดรหัสสตริงของเรา const buffer = Buffer.from(ข้อความ) console.log(บัฟเฟอร์); // <บัฟเฟอร์ e4 bd a0 e5 a5 bd e5 95 8a> // มีเมธอด toString ในบัฟเฟอร์อินสแตนซ์ที่สามารถถอดรหัสการเข้ารหัส console.log(buffer.toString()); // 'Hello'
จะเกิดอะไรขึ้นหากการเข้ารหัสและการถอดรหัสใช้ผลลัพธ์การเข้ารหัสในรูปแบบที่แตกต่างกัน
const message = 'Hello' const buffer = Buffer.from (ข้อความ 'utf16le') console.log(บัฟเฟอร์); // <บัฟเฟอร์ 60 4f 7d 59 4a 55> console.log(buffer.toString()); // `O}YJU
วิธีอื่นในการสร้างบัฟเฟอร์
มีหลายวิธีในการสร้าง buffer
ที่นี่เราสามารถสร้าง Buffer
ผ่าน alloc
ได้
โดยตรง
แก้ไข
เป็น
ตัวอย่างเช่น หากส่งผ่าน 8 ที่นี่ บัฟเฟอร์ที่สร้างขึ้นจะมี 8 องค์ประกอบ และเลขฐานสองที่สอดคล้องกับแต่ละองค์ประกอบจะเป็น 0 บัฟเฟอร์ const = Buffer.alloc (8) console.log(บัฟเฟอร์); // <บัฟเฟอร์ 00 00 00 00 00 00 00 00> // หากกำหนดค่าให้กับเลขฐานสิบ บัฟเฟอร์จะช่วยเราแปลงเป็นเลขฐานสิบหก จากนั้นเขียนลงในตำแหน่งบัฟเฟอร์[0] = 88 // ใน js สิ่งใดก็ตามที่ขึ้นต้นด้วย 0x จะแสดงเป็นบัฟเฟอร์เลขฐานสิบหก[1] = 0x88 console.log(buffer); // <Buffer 58 88 00 00 00 00 00 00>
การทำงานของบัฟเฟอร์และไฟล์
1. หากไฟล์ข้อความ
buffer
ดั้งเดิมจะถูกส่งกลับโดยตรง ซึ่งเป็นผลลัพธ์เนื้อหาไฟล์ utf-8
เข้ารหัสเลขฐานสองconst fs = need('fs') fs.readFile('./a.txt', (ผิดพลาด, ข้อมูล) => { console.log(ข้อมูล); // <บัฟเฟอร์ e5 93 88 e5 93 88> })
const fs = need('fs') // การเข้ารหัส หมายถึงการเข้ารหัสอักขระที่ใช้สำหรับการถอดรหัส และการเข้ารหัสจะมีค่าเริ่มต้นเป็น utf-8 fs.readFile('./a.txt', { การเข้ารหัส: 'utf-8' }, (ผิดพลาด ข้อมูล) => { console.log(data); // ฮ่าฮ่า})
const fs = need('fs') // การเข้ารหัสใช้การเข้ารหัสอักขระ utf16le และการถอดรหัสใช้รูปแบบ utf-8 จะต้องเป็นการถอดรหัสที่ไม่ถูกต้อง fs.readFile('./a.txt', { การเข้ารหัส: 'utf16le' } (ผิดพลาด , ข้อมูล) => { console.log(ข้อมูล); // ข้อผิดพลาด }) // โค้ดข้างต้นคล้ายกับโค้ดต่อไปนี้ const msg = 'Haha' const buffer = Buffer.from(msg, 'utf-8') console.log(buffer.toString('utf16le')); //
2. ไฟล์รูปภาพ
จะคัดลอกการเข้ารหัสรูปภาพเพื่อให้บรรลุวัตถุประสงค์ในการคัดลอก
encoding
เนื่องจากเป็นการเข้ารหัสอักขระ จะอ่านเมื่ออ่านรูปภาพเท่านั้น ซึ่งจะมีประโยชน์เมื่อดึงไฟล์ข้อความเท่านั้น fs.readFile('./logo.png', (ผิดพลาด, ข้อมูล) => { console.log(data); // สิ่งที่พิมพ์ออกมาคือการเข้ารหัสแบบไบนารี่ที่สอดคล้องกับไฟล์รูปภาพ // นอกจากนี้เรายังสามารถเขียนการเข้ารหัสรูปภาพไปยังไฟล์อื่นได้ ซึ่งเทียบเท่ากับการที่เราคัดลอกรูปภาพ fs.writeFile(' ./bar) .png' ข้อมูล ผิดพลาด => { console.log(ผิดพลาด); - })
sharp
const sharp = need('sharp') // ครอบตัดรูปภาพ logo.png เป็น 200x300 แล้วคัดลอกไปที่ไฟล์ bax.png sharp('./logo.png') .resize(200, 300) .toFile('./bax.png', (ผิดพลาด, ข้อมูล) => { console.log(ผิดพลาด); - // คุณยังสามารถแปลงไฟล์รูปภาพเป็นบัฟเฟอร์ก่อน แล้วจึงเขียนลงในไฟล์ คุณยังสามารถคัดลอกรูปภาพที่คมชัด('./logo.png') .resize(300, 300) .toBuffer() .แล้ว(ข้อมูล => { fs.writeFile('./baa.png', data, err => { console.log(ผิดพลาด); - })
กระบวนการสร้างบัฟเฟอร์
Buffer
เราจะไม่ได้ใช้หน่วยความจำจากระบบปฏิบัติการบ่อยนัก โดยค่าเริ่มต้นจะนำไปใช้กับหน่วยความจำขนาด 8 * 1024
ไบต์ก่อน นั่นคือ 8kb
เหตุการณ์วนซ้ำคืออะไร?
วงเหตุการณ์คืออะไร?
JS
ที่เราเขียนกับเบราว์เซอร์หรือ Node
JS
ที่เราเขียนและการเรียก API ของเบราว์เซอร์ ( setTimeout
, AJAX
,监听事件
ฯลฯ) ) บริดจ์สื่อสารผ่านฟังก์ชันการโทรกลับ ลูfile system
networ
ฯลฯ)กระบวนการและเธรด
กระบวนการและเธรดเป็นสองแนวคิดในระบบปฏิบัติการ:
process
): โปรแกรมที่คอมพิวเตอร์รันthread
): หน่วยที่เล็กที่สุดที่ระบบปฏิบัติการสามารถรันกำหนดการคำนวณได้ ดังนั้น CPU
จึงสามารถดำเนินการได้โดยตรง เธรดซึ่งฟังดูเป็นนามธรรมมาก เราจะอธิบายตามสัญชาตญาณ:
ลองใช้ตัวอย่างที่ชัดเจนเพื่ออธิบาย
ระบบปฏิบัติการ
แบบหลายเธรดที่สามารถพัฒนา
ได้และตรวจสอบข้อมูล) ทำงานไปพร้อมๆ กัน?
CPU
นั้นเร็วมาก และสามารถสลับระหว่างกระบวนการต่างๆ ได้อย่างรวดเร็วเบราว์เซอร์และ JavaScript
เรามักพูดว่า JavaScript
เป็นแบบเธรดเดียว แต่เธรด JS ควรมีกระบวนการคอนเทนเนอร์ของ Node
เอง
เบราว์เซอร์หรือเบราว์เซอร์ Node เป็นกระบวนการหรือไม่ มีเพียงเธรดเดียวในนั้นหรือไม่
tab
จะเริ่มต้นขึ้น เพื่อป้องกันไม่ให้หน้าหนึ่งติดขัดและทำให้ทุกหน้าไม่ตอบสนองอย่างไรก็ตาม การประมวลผลโค้ด JavaScript จะดำเนินการในเธรดที่แยกจากกัน
JS
สามารถทำสิ่งเดียวเท่านั้นในเวลากระบวนการดำเนินการ JavaScript
จะไม่ถูกดำเนินการจนกว่าจะถูกผลักเข้าไปในสแต็กการเรียกใช้ฟังก์ชัน มาวิเคราะห์กระบวนการดำเนินการของข้อความ
const = 'Hello World ' console.log(ข้อความ); ผลรวมของฟังก์ชัน (num1, num2) { กลับ num1 + num2 - ฟังก์ชั่นฟู() { ผลลัพธ์ const = ผลรวม (20, 30) console.log(ผลลัพธ์); - foo()
main
เหมือนกับภาษาโปรแกรมอื่นๆmessage
ตัวแปรlog
ฟังก์ชันจะถูกวาง เข้าสู่ฟังก์ชัน call stack หลังจากดำเนินการแล้ว ให้เปิดฟังก์ชันfoo
และเรียกใช้ฟังก์ชัน foo ลงในฟังก์ชัน call stack อย่างไรก็ตาม ฟังก์ชัน sum
จะต้องถูกเรียกใช้ระหว่างการดำเนินการjs
ทั้งหมดจะถูกดำเนินการ และฟังก์ชันหลักจะถูกดึงออกมาจากลูปเหตุการณ์ของเบราว์เซอร์
จะเกิดอะไรขึ้นหากมีการดำเนินการแบบอะซิงโครนัสระหว่างการเรียกใช้โค้ด JS
setTimeout
ไว้ตรงกลางจากนั้น ฟังก์ชันจะส่งผ่านไปยังฟังก์ชัน setTimeout (เราเรียกว่าฟังก์ชัน timer
) จะดำเนินการเมื่อใด?
web api
เบราว์เซอร์จะจัดเก็บฟังก์ชันการโทรกลับไว้ล่วงหน้า เมื่อถึงเวลาที่เหมาะสม ฟังก์ชันตัวจับเวลาจะถูกเพิ่มลงในคิวเหตุใด setTimeout จึงไม่บล็อกการทำงานของโค้ด
เป็นเพราะเบราว์เซอร์รักษาสิ่งที่สำคัญมากไว้ -
เบราว์เซอร์ลูปเหตุการณ์จะช่วยเราบันทึกฟังก์ชันการโทรกลับใน setTimeout ด้วยวิธีใดวิธีหนึ่ง วิธีทั่วไปคือบันทึกไว้ในแผนผังสีแดงดำ
และรอจนกว่าจะกำหนดเวลา setTimeout เมื่อถึงเวลาของตัวจับเวลา มันจะนำฟังก์ชันการเรียกกลับของตัวจับเวลาออกจากตำแหน่งที่บันทึกไว้และนำไปไว้ในคิวเหตุการณ์
เมื่อลูปเหตุการณ์พบว่ามีบางอย่างอยู่ในคิวของเรา และสแต็กการเรียกฟังก์ชันปัจจุบันว่างเปล่า หลังจากดำเนินการโค้ดการซิงโครไนซ์แล้ว ฟังก์ชันการโทรกลับในคิวของเราจะถูกแยกออกจากคิวและใส่ลงในสแต็กการเรียกฟังก์ชันเพื่อดำเนินการ (ฟังก์ชันถัดไปจะไม่ถูกผลักเข้าไปในสแต็กจนกว่าฟังก์ชันก่อนหน้าในคิวจะโผล่ออกมา)
แน่นอน จะต้องมีเพียงเหตุการณ์เดียวเท่านั้น ตัวอย่างเช่น ในระหว่างกระบวนการบางอย่าง ผู้ใช้คลิกปุ่มในเบราว์เซอร์ เราอาจมีจอภาพสำหรับการคลิกปุ่มนี้ ซึ่งสอดคล้องกับฟังก์ชันการโทรกลับ จะถูกเพิ่มเข้าไปในคิวของเราด้วย ลำดับการดำเนินการจะขึ้นอยู่กับลำดับที่อยู่ในคิวเหตุการณ์ นอกจากนี้ยังมีบทสรุปของการเรียกกลับที่เราส่งคำขอ ajax
ไปยังคิวเหตุการณ์
: อันที่จริง event loop เป็นสิ่งที่ง่ายมาก หมายความว่าเมื่อจำเป็นต้องดำเนินการโทรกลับบางอย่างภายใต้สถานการณ์พิเศษ การโทรกลับจะบันทึกไว้ ล่วงหน้าจะถูกยัดเข้าไปในคิวเหตุการณ์ และลูปเหตุการณ์จะนำมันออกมาและวางลงในสแต็กการเรียกใช้ฟังก์ชัน
งานแมโครและงานไมโคร
อย่างไรก็ตาม ลูปเหตุการณ์ไม่ได้รักษาเพียงคิวเดียว จริงๆ แล้ว มีสองคิว และการดำเนินการของงานในคิวต้องรอ
macrotask queue
ajax
setTimeout
, setInterval
, การตรวจสอบ DOM
, UI Rendering
และmicrotask queue
): then
Promise
จะโทรกลับ, Mutation Observer API
, queueMicrotask()
ฯลฯแล้วอะไรคือลำดับความสำคัญของสองคิวในลูปเหตุการณ์
main script
จะถูกดำเนินการก่อน (โค้ดสคริปต์ระดับบนสุดที่เขียน)ก่อน
จุดทดสอบ: main stcipt
, setTimeout
, Promise
then
, queueMicrotask
setTimeout(() => { console.log('set1');4 สัญญาใหม่ (แก้ไข => { แก้ไข() }).แล้ว(แก้ไข => { สัญญาใหม่ (แก้ไข => { แก้ไข() }).แล้ว(() => { console.log('แล้ว4'); - console.log('แล้ว2'); - - สัญญาใหม่ (แก้ไข => { console.log('pr1'); แก้ไข() }).แล้ว(() => { console.log('แล้ว1'); - setTimeout(() => { console.log('set2'); - คอนโซล.บันทึก(2); QueueMicrotask(() => { console.log('queueMicrotask'); - สัญญาใหม่ (แก้ไข => { แก้ไข() }).แล้ว(() => { console.log('แล้ว3'); - // pr1 // 2 //แล้ว1 //queueMicrotask //แล้ว3 // set1 //แล้ว2 //แล้ว4 // set2
setTimeout
จะถูกผลักเข้าไปใน function call stack ทันที และจะถูก popped ออกจาก stack ทันทีหลังจากดำเนินการ ฟังก์ชัน timer
จะถูกใส่เข้าไปในคิวงานมาโคร
ฟังก์ชันที่ส่งผ่านไปยังคลาส Promise
จะถูกดำเนินการทันที มันไม่ใช่ฟังก์ชันการโทรกลับ ดังนั้นจึงจะถูกพิมพ์ออกมา pr1
และเนื่องจากวิธี resolve
ถูกดำเนินการ สถานะของสัญญาจะเปลี่ยนเป็น fulfilled
ตาม ทันที ดังนั้นเมื่อฟังก์ชัน then
ถูกดำเนินการ ฟังก์ชันการโทรกลับที่เกี่ยวข้องจะ ถูกใส่ลงในคิวไมโครทาสก์และ
พบฟังก์ชัน setTimeout อีกครั้ง เมื่อสแต็กถูกเปิด ฟังก์ชันตัวจับเวลาจะถูกใส่ลงในคิวงานแมโคร
เมื่อพบคำสั่ง console.log
หลังจากที่ฟังก์ชันถูกพุชลงบนสแต็ 2
ถูกพิมพ์ออกมาแล้วเด้งออกมา
ฟังก์ชั่นถูกผูกไว้กับ queueMicrotask
ที่นี่ และฟังก์ชั่นจะถูกวาง หลังจากเข้าสู่คิว Microtask
จะพบคำสั่ง Promise ใหม่ แต่จะเปลี่ยนสถานะ Promise ทันที ดังนั้นการโทรกลับ ที่สอดคล้องกับฟังก์ชันนั้นก็ถูกใส่เข้าไปในคิวไมโครทาสก์ด้วย
เนื่องจากโค้ดสคริปต์การซิงโครไนซ์ได้รับการดำเนินการแล้ว ขณะนี้เหตุการณ์อยู่ที่จุดเริ่มต้นของลูป งานที่แข่งขันกับคิวไมโครทาสก์และงานมาโครจะถูกใส่ลงใน function call stack ตามลำดับความสำคัญ หมายเหตุ: ลำดับความสำคัญของงานขนาดเล็กนั้นสูงกว่างานมาโคร คุณต้องอ่านทุกครั้งก่อนต้องการดำเนินการงานมาโคร มันไม่ว่างเปล่า คุณต้องดำเนินการงานของคิวไมโครทาสก์ก่อน
ไมโครทาสก์แรกคือการพิมพ์ then1
ไมโครทาสก์ที่สองคือการพิมพ์คิวไมโครทาสก์ และไมโครทาสก์ที่สามคือการพิมพ์ จากนั้น then3
การดำเนินการเสร็จสิ้น เริ่มดำเนินการงานแมโคร
งานแมโครแรกมีความซับซ้อนมากขึ้น อันดับแรกจะพิมพ์ set1
จากนั้นจึงดำเนินการคำสั่ง new promise
ที่จะเปลี่ยนสถานะทันที คิวไม่ว่างเปล่า ดังนั้นจึงจำเป็นต้องดำเนินการคิวไมโครทาสก์ที่มีลำดับความสำคัญสูงกว่า ซึ่งเทียบเท่ากับการดำเนินการโทรกลับทันที ซึ่งเป็นคำสั่ง Promise ใหม่เดียวกัน และการสลับที่สอดคล้องกันนั้นจะถูกใส่ลงในคิวไมโครทาสก์ โปรดทราบว่ามีฟังก์ชัน console
หลังจากคำสั่ง Promise ใหม่ ฟังก์ชันนี้จะถูกดำเนินการทันทีหลังจากคำสั่ง Promise ใหม่ถูกดำเนินการ นั่นคือ การพิมพ์ then2
ยังมีงานในการเผชิญหน้าไมโครทาสก์ ดังนั้นขั้นตอนต่อไปคือการพิมพ์ then4
. จนถึงขณะนี้ คิวไมโครทาสก์ว่างเปล่า และคิวแมโครทาสก์สามารถดำเนินการต่อไปได้
ดังนั้นแมโครทาสก์ set2
2 ต่อไปจะถูกพิมพ์ หลังจากดำเนินการแมโครทาสก์แล้ว
ผลลัพธ์การพิมพ์ของโค้ดทั้งหมดจะเป็น: pr1 -> 2 -> then1 -> queueMicrotask -> then3 -> set1 -> then2 -> then4 -> set2
คำถามสัมภาษณ์ <2>
จุดทดสอบ: main script
setTimeout
, Promise
then
, queueMicrotask
, await
async
ส่วนเสริมความรู้ async: async, await เป็นไวยากรณ์น้ำตาล สำหรับ Promise
เมื่อจัดการกับปัญหาลูปเหตุการณ์
new Promise((resolve,rejcet) => { 函数执行})
then(res => {函数执行})
ในฟังก์ชัน Promiseasync ก่อนหน้า async1() { console.log('async1 เริ่มต้น'); รอ async2() console.log('async1 สิ้นสุด'); - ฟังก์ชันอะซิงก์ async2() { console.log('async2'); - console.log('สคริปต์เริ่มต้น'); setTimeout(() => { console.log('setTimeout'); }, 0) อะซิงก์1() สัญญาใหม่ (แก้ไข => { console.log('promise1'); แก้ไข() }).แล้ว(() => { console.log('promise2'); - console.log('สิ้นสุดสคริปต์'); // สคริปต์เริ่มต้น // เริ่มต้น async1 // async2 //สัญญา1 // สิ้นสุดสคริปต์ // สิ้นสุด async1 //สัญญา2 // setTimeout
เป็นคำจำกัดความของฟังก์ชันที่จุดเริ่มต้น และไม่จำเป็นต้องถูกผลักเข้าไปในสแต็กการเรียกฟังก์ชันเพื่อดำเนินการจนกว่าจะพบคำสั่ง console
แรก หลังจากกดสแต็กแล้ว ให้รัน script start
จากนั้นจึงนำออกจาก stack
เพื่อพบกับฟังก์ชัน setTimeout
แรก ซึ่งสอดคล้องกับ timer
จะถูกใส่ลงในคิวงานมาโคร
และฟังก์ชัน async1 จะถูกดำเนินการ ขั้นแรก async1 start
จะถูกพิมพ์ จากนั้นฟังก์ชัน async2
หลังจากคำสั่ง await
จะถูกดำเนินการ เพราะดังที่ได้กล่าวไว้ก่อนหน้านี้ ฟังก์ชันที่อยู่หลังคีย์เวิร์ด await ถือเป็น new Promise
ฟังก์ชันนี้จะถูกดำเนินการทันที ดังนั้น async2 จะถูกพิมพ์ออกมา แต่โค้ดที่อยู่หลังคำสั่ง await จะเทียบเท่ากับการใส่ลงใน callback กล่าวคือ console.log('async1 end')
บรรทัดของโค้ดนี้ถูกใส่ลงในคิว microtask
promise1
โค้ดยังคงดำเนินการต่อไป จากนั้นการโทรกลับจะถูกใส่ลงในคิวไมโครทาสก์เพื่อ
ดำเนินการฟังก์ชัน script end
การซิงโครไนซ์ได้ถูกดำเนินการแล้ว ลูปเหตุการณ์จะไปที่งานแมโครและคิวงานไมโครเพื่อดำเนินการงาน
อันดับแรก ไปที่ไมโคร คิวงาน คำสั่งการพิมพ์ที่สอดคล้องกับงานไมโครงานแรกจะถูกดำเนินการ ซึ่งหมายความว่า async1 end
จะถูกพิมพ์ จากนั้น promise2
จะถูกพิมพ์ ในเวลานี้ คิวไมโครทาสก์จะว่างเปล่า และงานในคิวงานแมโครจะเริ่มต้นขึ้น จะถูกดำเนินการ
setTimeout ที่สอดคล้องกับฟังก์ชันจับเวลาจะถูกพิมพ์ ในเวลานี้ งานแมโครจะถูกดำเนินการด้วย และลำดับการพิมพ์สุดท้ายคือ: script start -> async1 start -> async2 -> promise1 -> script end -> async1 end -> promise2 -> setTimeout