国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

用一道大廠面試題帶你搞懂事件循環(huán)機制

ShowerSun / 1476人閱讀

本文涵蓋

面試題的引入

對事件循環(huán)面試題執(zhí)行順序的一些疑問

通過面試題對微任務、事件循環(huán)、定時器等對深入理解

結(jié)論總結(jié)

面試題

面試題如下,大家可以先試著寫一下輸出結(jié)果,然后再看我下面的詳細講解,看看會不會有什么出入,如果把整個順序弄清楚 Node.js 的執(zhí)行順序應該就沒問題了。

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("setTimeout3") 
},3)  
setImmediate(() => console.log("setImmediate"));
process.nextTick(() => console.log("nextTick"));
async1();
new Promise(function(resolve){
    console.log("promise1")
    resolve();
    console.log("promise2")
}).then(function(){
    console.log("promise3")
})
console.log("script end")

面試題正確的輸出結(jié)果

script start
async1 start
async2
promise1
promise2
script end
nextTick
async1 end
promise3
setTimeout0
setImmediate
setTimeout3
提出問題

在理解node.js的異步的時候有一些不懂的地方,使用node.js的開發(fā)者一定都知道它是單線程的,異步不阻塞且高并發(fā)的一門語言,但是node.js在實現(xiàn)異步的時候,兩個異步任務開啟了,是就是誰快就誰先完成這么簡單,還是說異步任務最后也會有一個先后執(zhí)行順序?對于一個單線程的的異步語言它是怎么實現(xiàn)高并發(fā)的呢?

好接下來我們就帶著這兩個問題來真正的理解node.js中的異步(微任務與事件循環(huán))。

Node 的異步語法比瀏覽器更復雜,因為它可以跟內(nèi)核對話,不得不搞了一個專門的庫 libuv 做這件事。這個庫負責各種回調(diào)函數(shù)的執(zhí)行時間,異步任務最后基于事件循環(huán)機制還是要回到主線程,一個個排隊執(zhí)行。

詳細講解 1.本輪循環(huán)與次輪循環(huán)

異步任務可以分成兩種。

追加在本輪循環(huán)的異步任務

追加在次輪循環(huán)的異步任務

所謂”循環(huán)”,指的是事件循環(huán)(event loop)。這是 JavaScript 引擎處理異步任務的方式,后文會詳細解釋。這里只要理解,本輪循環(huán)一定早于次輪循環(huán)執(zhí)行即可。

Node 規(guī)定,process.nextTick和Promise的回調(diào)函數(shù),追加在本輪循環(huán),即同步任務一旦執(zhí)行完成,就開始執(zhí)行它們。而setTimeout、setInterval、setImmediate的回調(diào)函數(shù),追加在次輪循環(huán)。

2.process.nextTick()

1)process.nextTick不要因為有next就被好多小伙伴當作次輪循環(huán)

2)Node 執(zhí)行完所有同步任務,接下來就會執(zhí)行process.nextTick的任務隊列。

3)開發(fā)過程中如果想讓異步任務盡可能快地執(zhí)行,可以使用process.nextTick來完成。

3.微任務(microtack)

根據(jù)語言規(guī)格,Promise對象的回調(diào)函數(shù),會進入異步任務里面的”微任務”(microtask)隊列。

微任務隊列追加在process.nextTick隊列的后面,也屬于本輪循環(huán)。

根據(jù)語言規(guī)格,Promise對象的回調(diào)函數(shù),會進入異步任務里面的”微任務”(microtask)隊列。

微任務隊列追加在process.nextTick隊列的后面,也屬于本輪循環(huán)。所以,下面的代碼總是先輸出3,再輸出4。

process.nextTick(() => console.log(3));
Promise.resolve().then(() => console.log(4));

// 輸出結(jié)果3,4

process.nextTick(() => console.log(1));
Promise.resolve().then(() => console.log(2));
process.nextTick(() => console.log(3));
Promise.resolve().then(() => console.log(4));

// 輸出結(jié)果 1,3,2,4

注意,只有前一個隊列全部清空以后,才會執(zhí)行下一個隊列。兩個隊列的概念 nextTickQueue 和微隊列microTaskQueue,也就是說開啟異步任務也分為幾種,像promise對象這種,開啟之后直接進入微隊列中,微隊列內(nèi)的就是那個任務快就那個先執(zhí)行完,但是針對于隊列與隊列之間不同的任務,還是會有先后順序,這個先后順序是由隊列決定的。

4.事件循環(huán)的階段(idle, prepare忽略了這個階段)

事件循環(huán)最階段最詳細的講解(官網(wǎng):https://nodejs.org/en/docs/gu...)

timers階段

次階段包括setTimeout()和setInterval()

IO callbacks

大部分的回調(diào)事件,普通的caollback

poll階段

網(wǎng)絡連接,數(shù)據(jù)獲取,讀取文件等操作

check階段

setImmediate()在這里調(diào)用回調(diào)

close階段
一些關(guān)閉回調(diào),例如socket.on("close", ...)

事件循環(huán)注意點

1)Node 開始執(zhí)行腳本時,會先進行事件循環(huán)的初始化,但是這時事件循環(huán)還沒有開始,會先 完成下面的事情。

同步任務
發(fā)出異步請求
規(guī)劃定時器生效的時間
執(zhí)行process.nextTick()等等

最后,上面這些事情都干完了,事件循環(huán)就正式開始了。

2)事件循環(huán)同樣運行在單線程環(huán)境下,高并發(fā)也是依靠事件循環(huán),每產(chǎn)生一個事件,就會加入到該階段對應的隊列中,此時事件循環(huán)將該隊列中的事件取出,準備執(zhí)行之后的callback。

3)假設事件循環(huán)現(xiàn)在進入了某個階段,即使這期間有其他隊列中的事件就緒,也會先將當前隊列的全部回調(diào)方法執(zhí)行完畢后,再進入到下一個階段。

5.事件循環(huán)中的setTimeOut與setImmediate

由于setTimeout在 timers 階段執(zhí)行,而setImmediate在 check 階段執(zhí)行。所以,setTimeout會早于setImmediate完成。

setTimeout(() => console.log(1));
setImmediate(() => console.log(2));

上面代碼應該先輸出1,再輸出2,但是實際執(zhí)行的時候,結(jié)果卻是不確定,有時還會先輸出2,再輸出1。

這是因為setTimeout的第二個參數(shù)默認為0。但是實際上,Node 做不到0毫秒,最少也需要1毫秒,根據(jù)官方文檔,第二個參數(shù)的取值范圍在1毫秒到2147483647毫秒之間。也就是說,setTimeout(f, 0)等同于setTimeout(f, 1)。

實際執(zhí)行的時候,進入事件循環(huán)以后,有可能到了1毫秒,也可能還沒到1毫秒,取決于系統(tǒng)當時的狀況。如果沒到1毫秒,那么 timers 階段就會跳過,進入 check 階段,先執(zhí)行setImmediate的回調(diào)函數(shù)。

但是,下面的代碼一定是先輸出2,再輸出1。

const fs = require("fs");
fs.readFile("test.js", () => {
 setTimeout(() => console.log(1));
 setImmediate(() => console.log(2));
});

上面代碼會先進入 I/O callbacks 階段,然后是 check 階段,最后才是 timers 階段。因此,setImmediate才會早于setTimeout執(zhí)行。

6.同步任務中async以及promise的一些誤解

問題1:

在面試題中,在同步任務的過程中,不知道大家有沒有疑問,為什么不是執(zhí)行完async2輸出后執(zhí)行async1 end輸出,而是接著執(zhí)行promise1?

引用阮一峰老師書中一句話:“ async 函數(shù)返回一個 Promise 對象,當函數(shù)執(zhí)行的時候,一旦遇到 await 就會先返回,等到觸發(fā)的異步操作完成,再接著執(zhí)行函數(shù)體內(nèi)后面的語句。”

簡單的說,先去執(zhí)行后面的同步任務代碼,執(zhí)行完成后,也就是表達式中的 Promise 解析完成后繼續(xù)執(zhí)行 async 函數(shù)并返回解決結(jié)果。(其實還是本輪循環(huán)promise的問題,最后的resolve屬于異步,位于本輪循環(huán)的末尾。)

問題2:

console.log("promise2")為什么也是在resolve之前執(zhí)行?

解答:注:此內(nèi)容來源與阮一峰老師的ES6書籍,調(diào)用resolve或者reject并不會終結(jié)promise的參數(shù)函數(shù)的執(zhí)行。因為立即resolved的Promise是本輪循環(huán)的末尾執(zhí)行,同時總是晚于本輪循環(huán)的同步任務。正規(guī)的寫法調(diào)用resolve或者reject以后,Promise的使命就完成了,后繼操作應該放在then方法后面。所以最好在它的前面加上return語句,這樣就不會出現(xiàn)意外

new Promise((resolve,reject) => {
    return resolve(1);
    //后面的語句不會執(zhí)行
    console.log(2);
}

問題3:

promise3和script end的執(zhí)行順序是否有疑問?

解答:因為立即resolved的Promise是本輪循環(huán)的末尾執(zhí)行,同時總是晚于本輪循環(huán)的同步任務。 Promise 是一個立即執(zhí)行函數(shù),但是他的成功(或失敗:reject)的回調(diào)函數(shù) resolve 卻是一個異步執(zhí)行的回調(diào)。當執(zhí)行到 resolve() 時,這個任務會被放入到回調(diào)隊列中,等待調(diào)用棧有空閑時事件循環(huán)再來取走它。本輪循環(huán)中最后執(zhí)行的。

整體結(jié)論

順序的整體總結(jié)就是:
同步任務-> 本輪循環(huán)->次輪循環(huán)

附件:參考資料

node.js官網(wǎng):

事件循環(huán):https://nodejs.org/en/docs/gu...

Timers:https://nodejs.org/dist/lates...

加入我們一起學習吧!


node學習交流群

交流群滿100人不能自動進群, 請?zhí)砑尤褐治⑿盘?【coder_qi】備注node,自動拉你入群。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/106894.html

相關(guān)文章

  • 【Python從入門到實戰(zhàn)】一篇文章帶搞懂Python中的類~

    摘要:小栗子對于可樂來講,只要是同一個品牌的可樂,他們就有著同樣的成分,這被稱之為配方。小栗子對于可樂來說,按照配方把可樂生產(chǎn)出來的過程就是實例化的過程。小栗子類的屬性與正常的變量并無區(qū)別。 前言 我是栗子,帶大家從零開始學習Python,希望每篇文章都能讓你收獲滿滿! 今天我們要說的是面向?qū)ο蟮?..

    cloud 評論0 收藏0
  • 以??簡單易懂??的語言帶搞懂有監(jiān)督學習算法【附Python代碼詳解】機器學習系列之KNN篇

    必須要看的前言 本文風格:以??簡單易懂??的語言帶你徹底搞懂KNN,了解什么是有監(jiān)督學習算法。 認真看完這篇文章,徹底了解KNN、了解監(jiān)督學習算法絕對是一樣很簡單的事情。 注:本篇文章非常詳細,同時我也附加了Python代碼,歡迎收藏后慢慢閱讀。 目錄 必須要看的前言監(jiān)督學習算法KNN/K近鄰算法1 算法原理1.1 實現(xiàn)過程1.2 距離的確定 2 算法的優(yōu)缺點3 算法的變種3.1 變...

    MoAir 評論0 收藏0
  • 優(yōu)秀文章收藏(慢慢消化)持續(xù)更新~

    摘要:整理收藏一些優(yōu)秀的文章及大佬博客留著慢慢學習原文協(xié)作規(guī)范中文技術(shù)文檔協(xié)作規(guī)范阮一峰編程風格凹凸實驗室前端代碼規(guī)范風格指南這一次,徹底弄懂執(zhí)行機制一次弄懂徹底解決此類面試問題瀏覽器與的事件循環(huán)有何區(qū)別筆試題事件循環(huán)機制異步編程理解的異步 better-learning 整理收藏一些優(yōu)秀的文章及大佬博客留著慢慢學習 原文:https://www.ahwgs.cn/youxiuwenzhan...

    JeOam 評論0 收藏0
  • EventBus框架庫代碼走讀,帶你全面理解View的繪制流程

    摘要:如果當前不是主線程則直接調(diào)用,如果是線程則創(chuàng)建一個加入到后臺的一個隊列,最終由中的一個線程池去調(diào)用。拋出線程狀態(tài)非法異常。 while (clazz != null) {String name = clazz.getName();if (name.startsWith(java.) || name.starts...

    番茄西紅柿 評論0 收藏2637
  • 前端 100 問:能搞懂80%的請把簡歷給我

    摘要:解析第題第題為什么的和的中不能做異步操作解析第題第題京東下面代碼中在什么情況下會打印解析第題第題介紹下及其應用。盡量減少操作次數(shù)。解析第題第題京東快手周一算法題之兩數(shù)之和給定一個整數(shù)數(shù)組和一個目標值,找出數(shù)組中和為目標值的兩個數(shù)。 引言 半年時間,幾千人參與,精選大廠前端面試高頻 100 題,這就是「壹題」。 在 2019 年 1 月 21 日這天,「壹題」項目正式開始,在這之后每個工...

    Scott 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<