成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

從promise、process.nextTick、setTimeout出發(fā),談?wù)凟vent Loo

zero / 1782人閱讀

摘要:比如下面一個(gè)例子例輸出為先輸出,沒有問題,因?yàn)槭峭饺蝿?wù)在主線程中優(yōu)先執(zhí)行,這里的問題是和任務(wù)的執(zhí)行優(yōu)先級(jí)是如何定義的。

在原文的基礎(chǔ)上加了一點(diǎn)參考資料
問題的引出

event loop都不陌生,是指主線程從“任務(wù)隊(duì)列”中循環(huán)讀取任務(wù),比如

例1:

setTimeout(function(){console.log(1)},0);

console.log(2)

//輸出2,1

在上述的例子中,我們明白首先執(zhí)行主線程中的同步任務(wù),當(dāng)主線程任務(wù)執(zhí)行完畢后,再?gòu)膃vent loop中讀取任務(wù),因此先輸出2,再輸出1。

event loop讀取任務(wù)的先后順序,取決于任務(wù)隊(duì)列(Job queue)中對(duì)于不同任務(wù)讀取規(guī)則的限定。比如下面一個(gè)例子:

例2:

setTimeout(function () {
  console.log(3);
}, 0);

Promise.resolve().then(function () {
  console.log(2);
});
console.log(1);
//輸出為  1  2 3

先輸出1,沒有問題,因?yàn)槭峭饺蝿?wù)在主線程中優(yōu)先執(zhí)行,這里的問題是setTimeout和Promise.then任務(wù)的執(zhí)行優(yōu)先級(jí)是如何定義的。

2 . Job queue中的執(zhí)行順序
在Job queue中的隊(duì)列分為兩種類型:macro-task和microTask。我們舉例來(lái)看執(zhí)行順序的規(guī)定,我們?cè)O(shè)

macro-task隊(duì)列包含任務(wù): a1, a2 , a3
micro-task隊(duì)列包含任務(wù): b1, b2 , b3

執(zhí)行順序?yàn)?,首先?zhí)行marco-task隊(duì)列開頭的任務(wù),也就是 a1 任務(wù),執(zhí)行完畢后,在執(zhí)行micro-task隊(duì)列里的所有任務(wù),也就是依次執(zhí)行b1, b2 , b3,執(zhí)行完后清空micro-task中的任務(wù),接著執(zhí)行marco-task中的第二個(gè)任務(wù),依次循環(huán)。

了解完了macro-task和micro-task兩種隊(duì)列的執(zhí)行順序之后,我們接著來(lái)看,真實(shí)場(chǎng)景下這兩種類型的隊(duì)列里真正包含的任務(wù)(我們以node V8引擎為例),在node V8中,這兩種類型的真實(shí)任務(wù)順序如下所示:

macro-task隊(duì)列真實(shí)包含任務(wù):

script(主程序代碼),setTimeout, setInterval, setImmediate, I/O, UI rendering

micro-task隊(duì)列真實(shí)包含任務(wù):
process.nextTick, Promises, Object.observe, MutationObserver

由此我們得到的執(zhí)行順序應(yīng)該為:

script(主程序代碼)—>process.nextTick—>Promises...——>setTimeout——>setInterval——>setImmediate——> I/O——>UI rendering

在ES6中macro-task隊(duì)列又稱為ScriptJobs,而micro-task又稱PromiseJobs

3 . 真實(shí)環(huán)境中執(zhí)行順序的舉例
(1) setTimeout和promise
例3:

setTimeout(function () {
console.log(3);
}, 0);

Promise.resolve().then(function () {
console.log(2);
});

console.log(1);

我們先以第1小節(jié)的例子為例,這里遵循的順序?yàn)椋?/p>

script(主程序代碼)——>promise——>setTimeout
對(duì)應(yīng)的輸出依次為:1 ——>2————>3

(2) process.nextTick和promise、setTimeout
例子4:

setTimeout(function(){console.log(1)},0);

new Promise(function(resolve,reject){
   console.log(2);
   resolve();
}).then(function(){console.log(3)
}).then(function(){console.log(4)});

process.nextTick(function(){console.log(5)});

console.log(6);
//輸出2,6,5,3,4,1

這個(gè)例子就比較復(fù)雜了,這里要注意的一點(diǎn)在定義promise的時(shí)候,promise構(gòu)造部分是同步執(zhí)行的,這樣問題就迎刃而解了。

首先分析Job queue的執(zhí)行順序:

script(主程序代碼)——>process.nextTick——>promise——>setTimeout

I) 主體部分: 定義promise的構(gòu)造部分是同步的,
因此先輸出2 ,主體部分再輸出6(同步情況下,就是嚴(yán)格按照定義的先后順序)

II)process.nextTick: 輸出5

III)promise: 這里的promise部分,嚴(yán)格的說(shuō)其實(shí)是promise.then部分,輸出的是3,4

IV) setTimeout : 最后輸出1

綜合的執(zhí)行順序就是: 2——>6——>5——>3——>4——>1

(3)更復(fù)雜的例子

setTimeout(function(){console.log(1)},0);

new Promise(function(resolve,reject){
   console.log(2);
   setTimeout(function(){resolve()},0)
}).then(function(){console.log(3)
}).then(function(){console.log(4)});

process.nextTick(function(){console.log(5)});

console.log(6);

//輸出的是  2 6 5 1 3 4

這種情況跟我們(2)中的例子,區(qū)別在于promise的構(gòu)造中,沒有同步的resolve,因此promise.then在當(dāng)前的執(zhí)行隊(duì)列中是不存在的,只有promise從pending轉(zhuǎn)移到resolve,才會(huì)有then方法,而這個(gè)resolve是在一個(gè)setTimout時(shí)間中完成的,因此3,4最后輸出。

知識(shí)點(diǎn)參考

process.nextTick(callback)

process.nextTick()方法將 callback 添加到"next tick 隊(duì)列"。 一旦當(dāng)前事件輪詢隊(duì)列的任務(wù)全部完成,在next tick隊(duì)列中的所有callbacks會(huì)被依次調(diào)用。

這種方式不是setTimeout(fn, 0)的別名。它更加有效率。事件輪詢隨后的ticks 調(diào)用,會(huì)在任何I/O事件(包括定時(shí)器)之前運(yùn)行。

每次事件輪詢后,在額外的I/O執(zhí)行前,next tick隊(duì)列都會(huì)優(yōu)先執(zhí)行。 遞歸調(diào)用nextTick callbacks 會(huì)阻塞任何I/O操作,就像一個(gè)while(true) 循環(huán)一樣。

  function definitelyAsync(arg, cb) {
  if (arg) {
    process.nextTick(cb);
    return;
  }

  fs.stat("file", cb);  //涉及io操作
}
//這里process.nextTick就會(huì)阻塞io操作

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/96611.html

相關(guān)文章

  • Event Loop執(zhí)行順序

    摘要:簡(jiǎn)要介紹談?wù)勗陉?duì)列中的執(zhí)行順序問題的來(lái)源都不陌生,是指主線程從任務(wù)隊(duì)列中循環(huán)讀取任務(wù),比如例輸出在上述的例子中,我們明白首先執(zhí)行主線程中的同步任務(wù),當(dāng)主線程任務(wù)執(zhí)行完畢后,再?gòu)闹凶x取任務(wù),因此先輸出,再輸出。 簡(jiǎn)要介紹:談?wù)刾romise.resove,setTimeout,setImmediate,process.nextTick在EvenLoop隊(duì)列中的執(zhí)行順序 問題的來(lái)源 eve...

    kk_miles 評(píng)論0 收藏0
  • 瀏覽器和Node中的事件循環(huán)機(jī)制

    摘要:二瀏覽器端在講解事件循環(huán)之前先談?wù)勚型酱a異步代碼的執(zhí)行流程。三端我自己認(rèn)為的事件循環(huán)和瀏覽器端還是有點(diǎn)區(qū)別的,它的事件循環(huán)依靠引擎。四總結(jié)本篇主要介紹了瀏覽器和對(duì)于事件循環(huán)機(jī)制實(shí)現(xiàn),由于能力水平有限,其中可能有誤之處歡迎指出。 一、前言 前幾天聽公司一個(gè)公司三年的前端說(shuō)今天又學(xué)到了一個(gè)知識(shí)點(diǎn)-微任務(wù)、宏任務(wù),我問他這是什么東西,由于在吃飯他淺淺的說(shuō)了下,當(dāng)時(shí)沒太理解就私下學(xué)習(xí)整理一...

    KevinYan 評(píng)論0 收藏0
  • js 執(zhí)行機(jī)制 事件循環(huán)

    摘要:事件完成,回調(diào)函數(shù)進(jìn)入。我們來(lái)分析一段較復(fù)雜的代碼,看看你是否真的掌握了的執(zhí)行機(jī)制第一輪事件循環(huán)流程分析如下整體作為第一個(gè)宏任務(wù)進(jìn)入主線程,遇到,輸出。宏任務(wù)微任務(wù)第三輪事件循環(huán)宏任務(wù)執(zhí)行結(jié)束,執(zhí)行兩個(gè)微任務(wù)和。 關(guān)于JavaScript 首先js是單線程的,執(zhí)行任務(wù)肯定是一個(gè)接著一個(gè)。在最新的html5中提出了web-worker,但是JavaScript是單線程這一核心沒有改變,一...

    JackJiang 評(píng)論0 收藏0
  • 深入理解JavaScript運(yùn)行機(jī)制

    摘要:換句話說(shuō)當(dāng)一個(gè)異步過(guò)程調(diào)用發(fā)出后,調(diào)用者不會(huì)立刻得到結(jié)果,而是調(diào)用發(fā)出后,被調(diào)用者通過(guò)狀態(tài)通知或回調(diào)函數(shù)處理這個(gè)調(diào)用。 JavaScript單線程機(jī)制 JavaScript的一個(gè)語(yǔ)言特性(也是這門語(yǔ)言的核心)就是單線程。什么是單線程呢?簡(jiǎn)單地說(shuō)就是同一時(shí)間只能做一件事,當(dāng)有多個(gè)任務(wù)時(shí),只能按照一個(gè)順序一個(gè)完成了再執(zhí)行下一個(gè) 為什么JS是單線程的呢? JS最初被設(shè)計(jì)用在瀏覽器中,作為...

    phodal 評(píng)論0 收藏0
  • 瀏覽器與NodeJS的EventLoop異同,以及部分機(jī)制。

    摘要:瀏覽器與的異同,以及部分機(jī)制有人對(duì)部分迷惑,本身構(gòu)造函數(shù)是同步的,是異步。瀏覽器的的已全部分析完成,過(guò)程中引用阮一峰博客,知乎,部分文章內(nèi)容,侵刪。 瀏覽器與NodeJS的EventLoop異同,以及部分機(jī)制 PS:有人對(duì)promise部分迷惑,Promise本身構(gòu)造函數(shù)是同步的,.then是異步。---- 2018/7/6 22:35修改 javascript 是一門單線程的腳本...

    jubincn 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<