nodejs中怎么實現(xiàn)事件循環(huán)

nodejs中怎么實現(xiàn)事件循環(huán),針對這個問題,這篇文章詳細(xì)介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

成都創(chuàng)新互聯(lián)公司長期為上千家客戶提供的網(wǎng)站建設(shè)服務(wù),團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為安塞企業(yè)提供專業(yè)的成都網(wǎng)站制作、網(wǎng)站設(shè)計,安塞網(wǎng)站改版等技術(shù)服務(wù)。擁有十多年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。

當(dāng)Node.js啟動時會初始化event loop,每個event loop 都會包含按如下六個節(jié)點循環(huán),nodejs事件循環(huán)和瀏覽器事件循環(huán)完全不一樣。

nodejs中怎么實現(xiàn)事件循環(huán)

  • 圖中的每個方框被稱作事件循環(huán)的一個"階段",這6個階段為一輪事件循環(huán);

階段概覽
  • timers(定時器): 此階段執(zhí)行那些有setTimeout() 和 setInterval()調(diào)度的回調(diào)函數(shù);

  • I/O callbacks(I/O回調(diào)):此階段會執(zhí)行幾乎所有的回調(diào)函數(shù),除了close callbacks(關(guān)閉回調(diào)) 和 那些有timers與setImmediate()調(diào)度的回調(diào);

  • idle(空轉(zhuǎn)),prepare: 此階段只在內(nèi)部使用;

  • poll(輪詢): 檢索新的I/O事件;在恰當(dāng)?shù)臅r候Node會阻塞在這個節(jié)點;

  • check(檢查): setImmediate() 設(shè)置的回調(diào)會在此階段被調(diào)用;

  • close callbacks(關(guān)閉事件的回調(diào)):

    • 如:socket.on('close',...);此類的回調(diào)會在此階段被調(diào)用; 在事件循環(huán)每次運行之間,Node.js會檢查它是否等待異步I/O或定時器,如果沒有的話就會自動關(guān)閉;


如果event loop 進入了poll階段,且代碼未設(shè)定timer,將會發(fā)生下面的情況:

  • 如果poll queue不為空,event loop將同步的執(zhí)行queue里的callback,知道queue為空,或執(zhí)行的callback達到系統(tǒng)的上限;

  • 如果poll queue為空,將會發(fā)生下面的情況:

    • 如果代碼已經(jīng)被setImmediate()設(shè)定了callback,event loop 將結(jié)束poll階段進入check階段,并執(zhí)行check階段的queue(check階段的queue是setImmediate設(shè)定的)

    • 如果代碼沒有設(shè)定setImmediate(callback),event loop將阻塞在該階段等待callbacks加入poll queue,一旦達到就立即執(zhí)行;

如果event loop進入了poll階段,且代碼設(shè)定了timer:

  • 如果poll queue進入空狀態(tài)時(即poll階段為空閑狀態(tài)),event loop將阻塞在該階段等待callbacks加入poll queue,一旦達到就立即執(zhí)行;


setImmediate約定于setTimeout(cb,0)
  • path.resolve() 方法會把一個路徑或路徑片段的序列解析為一個絕對路徑。

  • __dirname 總是指向當(dāng)前文件夾的絕對路徑

  • __filename 總是指向當(dāng)前文件的絕對路徑

  • note:

    • io: 瀏覽器線程去調(diào)用一些異步的回調(diào)

  • 執(zhí)行代碼1

var fs = require('fs');
var path = require('path');
function someAsyncOperation(callback) {
  // 花費2ms
  fs.readFileSync('./read.txt', callback);
}
var timeoutScheduled = Date.now();
var fileReadTime = 0;
setTimeout(function() {
  var delay = Date.now() - timeoutScheduled;
  console.log(`setTimeout ${delay} ms have passed since I was sheculed`);
  console.log('fileReaderTime', fileReadTime - timeoutScheduled);
}, 10);

someAsyncOperation(function() {
  fileReadtime = Date.now();
  while (Date.now() - fileReadTime < 20) {}
});
  • 執(zhí)行過程:

    • setTimeout和readFile先后加入io

    • setTimeout執(zhí)行進入io;(需要10ms)

    • readfile執(zhí)行,也進入io;(需要2ms)

    • 2ms之后, redfile已經(jīng)讀取完畢,加入poll隊列,此時poll為空,執(zhí)行someAsyncOperation回調(diào);

    • 由于此回調(diào)有while,這里阻塞20ms;執(zhí)行完為22ms

    • 在10ms時,setTimeout不能執(zhí)行,因為js是單線程,setTimeout一直被阻塞

    • 執(zhí)行完之后(22ms以后),poll 進入空閑狀態(tài)

    • event loop檢查timer,setTimeout回調(diào);

  • 執(zhí)行結(jié)果:

    • readFile執(zhí)行22ms

    • setTimeout執(zhí)行22ms之后

  • 執(zhí)行代碼2

var fs = require('fs');
var path = require('path');
function someAsyncOperation(callback) {
  // 花費9ms
  fs.readFileSync('./read.txt', callback);
}
var timeoutScheduled = Date.now();
var fileReadTime = 0;
setTimeout(function() {
  var delay = Date.now() - timeoutScheduled;
  console.log(`setTimeout ${delay} ms have passed since I was sheculed`);
  console.log('fileReaderTime', fileReadTime - timeoutScheduled);
}, 5);

someAsyncOperation(function() {
  fileReadtime = Date.now();
  while (Date.now() - fileReadTime < 20) {}
});
  • 執(zhí)行結(jié)果

    • setTimeout執(zhí)行:5ms

    • readFile執(zhí)行9 ~ 29ms

  • 執(zhí)行代碼3

  • 在nodejs中,setTimeout(fn,0) === setTimeout(fn,0)

  • 在瀏覽器中,setTimeout(fn,0) === setTimeout(fn,4)

setImmediate(() =>{
    console.log('setImmediate')
},0)

setTimeout(() =>{
    console.log('setTimeout')
},0)

// setTimeout 和 setImmediate的執(zhí)行順序不確定
// 因為event loop的啟動也是需要時間的,可能執(zhí)行到poll階段時已經(jīng)超過了1ms,此時setTimeout會先執(zhí)行
const fs = require('fs');
const path = require('path');
fs.readFile(path.resolve(__dirname, '/read.txt'), () => {
  setTimeout(() => {
    console.log('setTimeout');
  }, 0);
  setImmediate(() => {
    console.log('setImmediate');
  }, 0);
});
// 執(zhí)行順序是確定的, setImmediate,setTimeout
  • 執(zhí)行過程:

    • 執(zhí)行fs,第一輪主線程沒有timer和setImmediate

    • 假設(shè)readFile需要2ms,執(zhí)行回調(diào)

    • 由poll進入check,setImmediate會先調(diào)用

    • 在第二輪的timer階段,會執(zhí)行setTimeout

關(guān)于nodejs中怎么實現(xiàn)事件循環(huán)問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識。

網(wǎng)站欄目:nodejs中怎么實現(xiàn)事件循環(huán)
鏈接地址:http://bm7419.com/article46/pcgjhg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計、商城網(wǎng)站、小程序開發(fā)、微信公眾號、營銷型網(wǎng)站建設(shè)、軟件開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

綿陽服務(wù)器托管