最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

node.js事件循環(huán)機(jī)制及與js區(qū)別詳解

 更新時(shí)間:2022年09月26日 09:24:02   作者:別救了這猴子廢了  
這篇文章主要為大家介紹了node.js事件循環(huán)機(jī)制及與js區(qū)別詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

一、是什么

瀏覽器事件循環(huán)(opens new window)中,我們了解到javascript在瀏覽器中的事件循環(huán)機(jī)制,其是根據(jù)HTML5定義的規(guī)范來實(shí)現(xiàn)

而在NodeJS中,事件循環(huán)是基于libuv實(shí)現(xiàn),libuv是一個(gè)多平臺(tái)的專注于異步IO的庫,如下圖最右側(cè)所示:

上圖EVENT_QUEUE 給人看起來只有一個(gè)隊(duì)列,但EventLoop存在6個(gè)階段,每個(gè)階段都有對應(yīng)的一個(gè)先進(jìn)先出的回調(diào)隊(duì)列

二、流程

上節(jié)講到事件循環(huán)分成了六個(gè)階段,對應(yīng)如下:

  • timers階段:這個(gè)階段執(zhí)行timer(setTimeout、setInterval)的回調(diào)
  • 定時(shí)器檢測階段(timers):本階段執(zhí)行 timer 的回調(diào),即 setTimeout、setInterval 里面的回調(diào)函數(shù)
  • I/O事件回調(diào)階段(I/O callbacks):執(zhí)行延遲到下一個(gè)循環(huán)迭代的 I/O 回調(diào),即上一輪循環(huán)中未被執(zhí)行的一些I/O回調(diào)
  • 閑置階段(idle, prepare):僅系統(tǒng)內(nèi)部使用
  • 輪詢階段(poll):檢索新的 I/O 事件;執(zhí)行與 I/O 相關(guān)的回調(diào)(幾乎所有情況下,除了關(guān)閉的回調(diào)函數(shù),那些由計(jì)時(shí)器和 setImmediate() 調(diào)度的之外),其余情況 node 將在適當(dāng)?shù)臅r(shí)候在此阻塞
  • 檢查階段(check):setImmediate() 回調(diào)函數(shù)在這里執(zhí)行
  • 關(guān)閉事件回調(diào)階段(close callback):一些關(guān)閉的回調(diào)函數(shù),如:socket.on('close', ...)

每個(gè)階段對應(yīng)一個(gè)隊(duì)列,當(dāng)事件循環(huán)進(jìn)入某個(gè)階段時(shí), 將會(huì)在該階段內(nèi)執(zhí)行回調(diào),直到隊(duì)列耗盡或者回調(diào)的最大數(shù)量已執(zhí)行, 那么將進(jìn)入下一個(gè)處理階段

除了上述6個(gè)階段,還存在process.nextTick,其不屬于事件循環(huán)的任何一個(gè)階段,它屬于該階段與下階段之間的過渡, 即本階段執(zhí)行結(jié)束, 進(jìn)入下一個(gè)階段前, 所要執(zhí)行的回調(diào),類似插隊(duì)

流程圖如下所示:

Node中,同樣存在宏任務(wù)和微任務(wù),與瀏覽器中的事件循環(huán)相似

微任務(wù)對應(yīng)有:

  • next tick queue:process.nextTick
  • other queue:Promise的then回調(diào)、queueMicrotask

宏任務(wù)對應(yīng)有:

  • timer queue:setTimeout、setInterval
  • poll queue:IO事件
  • check queue:setImmediate
  • close queue:close事件

其執(zhí)行順序?yàn)椋?/p>

  • next tick microtask queue
  • other microtask queue
  • timer queue
  • poll queue
  • check queue
  • close queue

三、題目

通過上面的學(xué)習(xí),下面開始看看題目

async function async1() {
    console.log('async1 start')
    await async2()
    console.log('async1 end')
}
async function async2() {
    console.log('async2')
}
console.log('script start')
setTimeout(function () {
    console.log('setTimeout0')
}, 0)
setTimeout(function () {
    console.log('setTimeout2')
}, 300)
setImmediate(() => console.log('setImmediate'));
process.nextTick(() => console.log('nextTick1'));
async1();
process.nextTick(() => console.log('nextTick2'));
new Promise(function (resolve) {
    console.log('promise1')
    resolve();
    console.log('promise2')
}).then(function () {
    console.log('promise3')
})
console.log('script end')

分析過程:

  • 先找到同步任務(wù),輸出script start
  • 遇到第一個(gè) setTimeout,將里面的回調(diào)函數(shù)放到 timer 隊(duì)列中
  • 遇到第二個(gè) setTimeout,300ms后將里面的回調(diào)函數(shù)放到 timer 隊(duì)列中
  • 遇到第一個(gè)setImmediate,將里面的回調(diào)函數(shù)放到 check 隊(duì)列中
  • 遇到第一個(gè) nextTick,將其里面的回調(diào)函數(shù)放到本輪同步任務(wù)執(zhí)行完畢后執(zhí)行
  • 執(zhí)行 async1函數(shù),輸出 async1 start
  • 執(zhí)行 async2 函數(shù),輸出 async2,async2 后面的輸出 async1 end進(jìn)入微任務(wù),等待下一輪的事件循環(huán)
  • 遇到第二個(gè),將其里面的回調(diào)函數(shù)放到本輪同步任務(wù)執(zhí)行完畢后執(zhí)行
  • 遇到 new Promise,執(zhí)行里面的立即執(zhí)行函數(shù),輸出 promise1、promise2
  • then里面的回調(diào)函數(shù)進(jìn)入微任務(wù)隊(duì)列
  • 遇到同步任務(wù),輸出 script end
  • 執(zhí)行下一輪回到函數(shù),先依次輸出 nextTick 的函數(shù),分別是 nextTick1、nextTick2
  • 然后執(zhí)行微任務(wù)隊(duì)列,依次輸出 async1 end、promise3
  • 執(zhí)行timer 隊(duì)列,依次輸出 setTimeout0
  • 接著執(zhí)行 check 隊(duì)列,依次輸出 setImmediate
  • 300ms后,timer 隊(duì)列存在任務(wù),執(zhí)行輸出 setTimeout2

執(zhí)行結(jié)果如下:

script start
async1 start
async2
promise1
promise2
script end
nextTick1
nextTick2
async1 end
promise3
setTimeout0
setImmediate
setTimeout2

最后有一道是關(guān)于setTimeoutsetImmediate的輸出順序

setTimeout(() => {
  console.log("setTimeout");
}, 0);
setImmediate(() => {
  console.log("setImmediate");
});

輸出情況如下:

情況一:
setTimeout
setImmediate

情況二:
setImmediate
setTimeout

分析下流程:

  • 外層同步代碼一次性全部執(zhí)行完,遇到異步API就塞到對應(yīng)的階段
  • 遇到setTimeout,雖然設(shè)置的是0毫秒觸發(fā),但實(shí)際上會(huì)被強(qiáng)制改成1ms,時(shí)間到了然后塞入times階段
  • 遇到setImmediate塞入check階段
  • 同步代碼執(zhí)行完畢,進(jìn)入Event Loop
  • 先進(jìn)入times階段,檢查當(dāng)前時(shí)間過去了1毫秒沒有,如果過了1毫秒,滿足setTimeout條件,執(zhí)行回調(diào),如果沒過1毫秒,跳過
  • 跳過空的階段,進(jìn)入check階段,執(zhí)行setImmediate回調(diào)

這里的關(guān)鍵在于這1ms,如果同步代碼執(zhí)行時(shí)間較長,進(jìn)入Event Loop的時(shí)候1毫秒已經(jīng)過了,setTimeout先執(zhí)行,如果1毫秒還沒到,就先執(zhí)行了setImmediate

以上就是node.js事件循環(huán)機(jī)制及與js區(qū)別詳解的詳細(xì)內(nèi)容,更多關(guān)于node.js事件循環(huán)與js區(qū)別的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論

安顺市| 崇礼县| 米脂县| 噶尔县| 板桥市| 民勤县| 广安市| 湾仔区| 朔州市| 乌兰察布市| 前郭尔| 临西县| 恭城| 桃源县| 巴中市| 富裕县| 隆回县| 金寨县| 克山县| 加查县| 八宿县| 阳曲县| 阳原县| 锡林浩特市| 丁青县| 巴青县| 澳门| 宝丰县| 澄迈县| 仙游县| 新化县| 永德县| 娱乐| 高唐县| 咸丰县| 福泉市| 萍乡市| 商洛市| 镇巴县| 清徐县| 旬阳县|