Rumah  >  Artikel  >  hujung hadapan web  >  Artikel ini akan membawa anda memahami baris gilir pemasa dalam gelung acara Nod

Artikel ini akan membawa anda memahami baris gilir pemasa dalam gelung acara Nod

青灯夜游
青灯夜游ke hadapan
2023-04-14 15:10:251433semak imbas

Artikel ini akan membawa anda memahami baris gilir pemasa dalam gelung acara Nod

Dalam artikel sebelumnya kami membincangkan baris gilir microtask dan susunan keutamaannya dalam setiap baris gilir. Dalam artikel ini, kita akan membincangkan baris gilir pemasa, baris gilir lain dalam Node.js untuk mengendalikan kod tak segerak.

Sebelum kita menyelidiki baris gilir pemasa, mari kita lihat sebentar baris gilir microtask. Untuk memasukkan fungsi panggil balik ke dalam baris gilir microtask, kami menggunakan fungsi seperti process.nextTick() dan Promise.resolve(). Barisan gilir Microtask mempunyai keutamaan tertinggi apabila ia datang untuk melaksanakan kod tak segerak dalam Node.js. [Cadangan tutorial berkaitan: tutorial video nodejs, Pengajaran pengaturcaraan]

Fungsi panggil balik beratur

Sekarang kita pergi ke Pemasa beratur. Untuk membuat baris gilir fungsi panggil balik ke dalam baris gilir pemasa, kita boleh menggunakan fungsi seperti setTimeout dan setInterval. Untuk memudahkan penjelasan, artikel ini akan menggunakan setTimeout.

Untuk memahami urutan pelaksanaan baris gilir pemasa, kami akan menjalankan satu siri eksperimen untuk membuat baris gilir tugasan dalam baris gilir microtask dan baris gilir pemasa.

Eksperimen 3

Kod

// index.js
setTimeout(() => console.log("this is setTimeout 1"), 0);
setTimeout(() => console.log("this is setTimeout 2"), 0);
setTimeout(() => console.log("this is setTimeout 3"), 0);

process.nextTick(() => console.log("this is process.nextTick 1"));
process.nextTick(() => {
  console.log("this is process.nextTick 2");
  process.nextTick(() =>
    console.log("this is the inner next tick inside next tick")
  );
});
process.nextTick(() => console.log("this is process.nextTick 3"));

Promise.resolve().then(() => console.log("this is Promise.resolve 1"));
Promise.resolve().then(() => {
  console.log("this is Promise.resolve 2");
  process.nextTick(() =>
    console.log("this is the inner next tick inside Promise then block")
  );
});
Promise.resolve().then(() => console.log("this is Promise.resolve 3"));

Anotasi: Jangan gugup, kod ini Berdasarkan artikel sebelumnya "Eksperimen Kebajikan", tiga setTimeout ayat telah ditambah pada permulaan.

Kod ini mengandungi tiga panggilan ke process.nextTick(), tiga panggilan ke Promise.resolve() dan tiga panggilan ke setTimeout. Setiap fungsi panggil balik log mesej yang sesuai. Ketiga-tiga panggilan setTimeout mempunyai kelewatan 0ms, yang bermaksud bahawa apabila setiap penyataan setTimeout dilaksanakan, fungsi panggil balik segera dimasukkan ke baris gilir pemasa untuk menunggu. Kedua-dua process.nextTick() dan kedua Promise.resolve() mempunyai pernyataan process.nextTick() tambahan, dan setiap satu disertakan dengan fungsi panggil balik.

Visualisasi

Artikel ini akan membawa anda memahami baris gilir pemasa dalam gelung acara Nod

Apabila tindanan panggilan melaksanakan semua pernyataan, terdapat 3 panggilan balik dalam baris gilir nextTick dan 3 panggilan balik dalam Promise beratur. 3 panggilan balik, terdapat juga 3 panggilan balik dalam baris gilir pemasa. Tiada kod untuk melaksanakan dan mengawal pas ke gelung acara.

Baris gilir nextTick mempunyai keutamaan tertinggi, diikuti oleh baris gilir Janji, kemudian baris gilir pemasa. Dapatkan panggilan balik pertama dari baris gilir nextTick dan laksanakannya, log mesej ke konsol. Kemudian dapatkan panggilan balik ke-2 dan laksanakannya, yang juga akan log mesej. Panggilan balik kedua mengandungi panggilan ke process.nextTick(), yang menambahkan panggilan balik baharu pada baris gilir nextTick. Teruskan pelaksanaan dan dapatkan serta laksanakan panggilan balik ke-3 dan log mesej. Akhir sekali, kami mengeluarkan fungsi panggil balik yang baru ditambahkan pada baris gilir nextTick dan melaksanakannya dalam timbunan panggilan, dengan itu mengeluarkan mesej log keempat pada konsol.

Apabila baris gilir nextTick kosong, gelung acara bertukar kepada baris gilir Promise. Dapatkan panggilan balik pertama dari baris gilir dan cetak mesej ke konsol Panggilan balik kedua mempunyai kesan yang sama dan juga menambah panggilan balik pada baris gilir nextTick. Panggilan balik ketiga dalam Janji dilaksanakan, dan mesej log dikeluarkan. Pada masa ini, baris gilir Promise kosong dan gelung acara menyemak baris gilir nextTick untuk melihat sama ada terdapat panggilan balik baharu Setelah ditemui, mesej itu juga dilog masuk ke konsol.

Sekarang kedua-dua baris gilir microtask kosong, gelung acara beralih ke baris gilir pemasa. Kami mempunyai tiga panggilan balik, setiap satunya diambil daripada baris gilir pemasa dan dilaksanakan pada timbunan panggilan, masing-masing akan mencetak "setTimeout 1", "setTimeout 2" dan "setTimeout 3".

this is process.nextTick 1
this is process.nextTick 2
this is process.nextTick 3
this is the inner next tick inside next tick
this is Promise.resolve 1
this is Promise.resolve 2
this is Promise.resolve 3
this is the inner next tick inside Promise then block
this is setTimeout 1
this is setTimeout 2
this is setTimeout 3

Inferens

Fungsi panggil balik dalam baris gilir microtask akan dilaksanakan sebelum fungsi panggil balik dalam baris gilir pemasa.

Setakat ini, susunan keutamaan ialah baris gilir nextTick, diikuti dengan baris gilir Janji, dan kemudian baris gilir pemasa. Sekarang mari kita beralih ke percubaan seterusnya.

Eksperimen 4

// index.js
setTimeout(() => console.log("this is setTimeout 1"), 0);
setTimeout(() => {
  console.log("this is setTimeout 2");
  process.nextTick(() =>
    console.log("this is inner nextTick inside setTimeout")
  );
}, 0);
setTimeout(() => console.log("this is setTimeout 3"), 0);

process.nextTick(() => console.log("this is process.nextTick 1"));
process.nextTick(() => {
  console.log("this is process.nextTick 2");
  process.nextTick(() =>
    console.log("this is the inner next tick inside next tick")
  );
});
process.nextTick(() => console.log("this is process.nextTick 3"));

Promise.resolve().then(() => console.log("this is Promise.resolve 1"));
Promise.resolve().then(() => {
  console.log("this is Promise.resolve 2");
  process.nextTick(() =>
    console.log("this is the inner next tick inside Promise then block")
  );
});
Promise.resolve().then(() => console.log("this is Promise.resolve 3"));

Kod untuk percubaan keempat kebanyakannya sama dengan percubaan ketiga, dengan satu pengecualian. Fungsi panggil balik dihantar ke fungsi setTimeout kedua kini mengandungi panggilan ke process.nextTick().

Visualisasi

assets_YJIGb4i01jvw0SRdL5Bt_c4034ba006d840128b729005183abdf4_compressed (1).gif

让我们应用从之前的实验中学到的知识,快进到回调在微任务队列中已经被执行的点。假设我们有三个回调在计时器队列中排队等待。第一个回调出队并在调用堆栈上执行,“setTimeout 1”消息打印到控制台。事件循环继续运行第二个回调,“setTimeout 2”消息打印到控制台。同时,也会有一个回调函数入队了 nextTick 队列。

在执行计时器队列中的每个回调后,事件循环会返回检查微任务队列。检查 nextTick 队列确定需要执行的回调函数。这时第二个 setTimeout 推入的回调函数出队并在调用栈上执行,结果“inner nextTick”消息打印到控制台。

现在微任务队列为空了,控制权返回到计时器队列,最后一个回调被执行,控制台上显示消息“setTimeout 3”。

this is process.nextTick 1
this is process.nextTick 2
this is process.nextTick 3
this is the inner next tick inside next tick
this is Promise.resolve 1
this is Promise.resolve 2
this is Promise.resolve 3
this is the inner next tick inside Promise then block
this is setTimeout 1
this is setTimeout 2
this is inner nextTick inside setTimeout
this is setTimeout 3

推论

微任务队列中的回调函数会在定时器队列中的回调函数执行之间被执行。

实验五

代码

// index.js
setTimeout(() => console.log("this is setTimeout 1"), 1000);
setTimeout(() => console.log("this is setTimeout 2"), 500);
setTimeout(() => console.log("this is setTimeout 3"), 0);

该代码包含三个 setTimeout 语句,包含三个不同的、入队时机不一样的回调函数。第一个 setTimeout 延迟 1000 毫秒,第二个延迟 500 毫秒,第三个延迟 0 毫秒。当执行这些回调函数时,它们只是简单地将一条消息记录到控制台中。

可视化

由于代码片段的执行非常简单,因此我们将跳过可视化实验。当多个 setTimeout 调用被发出时,事件循环首先排队最短延迟的一个并在其他之前执行。结果,我们观察到“setTimeout 3”先执行,然后是“setTimeout 2”,最后是“setTimeout 1”。

this is setTimeout 3
this is setTimeout 2
this is setTimeout 1

推论

计时器队列回调按照先进先出(FIFO)的顺序执行。

总结

实验表明,微任务队列中的回调比定时器队列中的回调具有更高优先级,并且微任务队列中的回调在定时器队列中的回调之间执行。定时器队列遵循先进先出(FIFO)顺序。

原文链接:Visualizing The Timer Queue in Node.js Event Loop,2023年4月4日,by Vishwas Gopinath

更多node相关知识,请访问:nodejs 教程

Atas ialah kandungan terperinci Artikel ini akan membawa anda memahami baris gilir pemasa dalam gelung acara Nod. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:juejin.cn. Jika ada pelanggaran, sila hubungi admin@php.cn Padam