
ไบนารีข้อมูล
เนื้อหาทั้งหมดในคอมพิวเตอร์: ข้อความ ตัวเลข รูปภาพ เสียง และวิดีโอ จะถูกแสดงด้วยไบนารี่ในที่สุด
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 bitbyte แล้ว 8 บิตจะรวมกันเป็นหน่วยหนึ่ง1 byte = 8 bit , 1kb = 1024 byte , 1M = 1024kb , 1 G = 1024 Mint ในภาษาการเขียนโปรแกรมหลายภาษาคือ 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(ผิดพลาด);
-
}) sharpconst 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 ที่เราเขียนกับเบราว์เซอร์หรือ NodeJS ที่เราเขียนและการเรียก 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 queueajaxsetTimeout , 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