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

資訊專欄INFORMATION COLUMN

任務(wù)、微任務(wù)、隊列以及調(diào)度

Miyang / 1885人閱讀

摘要:每次事件循環(huán)中,如果沒有其他運行并且任務(wù)都執(zhí)行完畢了,那么微任務(wù)就會在回調(diào)之后被執(zhí)行。在微任務(wù)中排隊的任何其他微任務(wù)將被添加到隊列的末尾并進行處理。因此一個已的調(diào)用時將立即把一個任務(wù)加入任務(wù)隊列。

原文地址(英):https://jakearchibald.com/201...

當我告訴Matt Gaunt(作者的同事),我正在謀劃寫一篇關(guān)于在瀏覽器事件循環(huán)(event loop)體系中微任務(wù)( microtask )的隊列和執(zhí)行的文章時,他說:“實話告訴你Jake,我對這篇文章是不會感興趣的”。好吧,不管怎樣,既然我已經(jīng)寫了那就讓我們坐下來好好享受它,好嗎?

事實上,如果視頻更符合你的胃口,那么Philips Roberts 在JSConf上關(guān)于event loop的演講會是很好的參考(該演講不涉及微任務(wù)(microtask),但是對事件循環(huán)的其他部分都講得非常好),閑話少說,開始我們的內(nèi)容。

    以下是一小段JavaScript:
    
    console.log("script start");
    
    setTimeout(function() {
      console.log("setTimeout");
    }, 0);
    
    Promise.resolve().then(function() {
      console.log("promise1");
    }).then(function() {
      console.log("promise2");
    });
    
    console.log("script end");

想想看控制臺會按照什么樣的順序打印結(jié)果呢?

正確的答案是:script start, script end, promise1, promise2, setTimeout,但是在不同的瀏覽器上結(jié)果可能會有所不同。

Microsoft Edge, Firefox 40, iOS Safari和桌面版Safari 8.0.8會在promise1,promise2之前打印出setTimeout,雖然這可能是瀏覽器廠商間各自競爭的結(jié)果,但這未免有些奇怪,因為Firefox 39和Safari 8.0.7得到的結(jié)果始終是正確的。

為什么會是這樣

為了搞清楚緣由,你需要明白事件循環(huán)(event loop)是如何處理任務(wù)(tasks)和微任務(wù)(microtasks)的.當這些名詞第一次出現(xiàn)的時候,你可能會感到頭疼,沒關(guān)系,深呼吸...

每一個"線程"都擁有屬于自己的事件循環(huán)(event loop),也就意味著每一個web worker都會存在自有的事件循環(huán)并獨立運行互不干擾。然而所有同源窗口之間共享一個事件循環(huán)(event loop),這樣它們就可以同步通信了(譯者注:根據(jù)HTML5.2規(guī)范,事件循環(huán)分兩種,一種是瀏覽器上下文的,一種是web worker的)。事件循環(huán)(event loop)總是不斷的運行,執(zhí)行隊列中的任務(wù)(task)。一個事件循環(huán)存在多個任務(wù)源,這確保了任務(wù)在特定任務(wù)源的執(zhí)行順序(譯者注:同一個任務(wù)源的任務(wù)將被添加到相同任務(wù)隊列,不同任務(wù)源的任務(wù)可能被添加到不同任務(wù)隊列),但是在每一次的循環(huán)中,瀏覽器會自主選擇哪個源的任務(wù)優(yōu)先執(zhí)行,這確保了一些性能敏感的任務(wù)的優(yōu)先級,比如用戶輸入。

任務(wù)(tasks,譯者注:也叫macro-task)被放到任務(wù)源中,瀏覽器內(nèi)部執(zhí)行轉(zhuǎn)移到JavaScript/DOM領(lǐng)域,并且確保這些 tasks按序執(zhí)行。在tasks執(zhí)行期間,瀏覽器可能更新渲染。來自鼠標點擊的事件回調(diào)需要安排一個task,解析HTML和setTimeout同樣需要。

setTimeout等待了給定的延遲時間之后就會為它的回調(diào)創(chuàng)建一個新的任務(wù)。這就是為什么setTimeout在script end之后打印script start,因為script end是歸屬于第一個任務(wù),而setTimeout對應(yīng)的是另一個任務(wù),至此,我們快要搞清楚了,我需要你們有足夠的耐心看完下一個部分

微任務(wù)(Microtasks)隊列通常用于存放一些任務(wù),這些任務(wù)應(yīng)該在正在執(zhí)行的腳本之后立即執(zhí)行,比如對一批動作作出反應(yīng),或者操作異步執(zhí)行避免創(chuàng)建整個新任務(wù)造成的性能浪費。每次事件循環(huán)中,如果沒有其他JavaScript運行并且任務(wù)(task)都執(zhí)行完畢了,那么微任務(wù)就會在回調(diào)之后被執(zhí)行。在微任務(wù)中排隊的任何其他微任務(wù)將被添加到隊列的末尾并進行處理。微任務(wù)包括 MutationObserverPromise的回調(diào)(譯者注:微任務(wù)包括:process.nextTick(Nodejs), Promises, Object.observe, MutationObserver;任務(wù)(tasks)包括:script(整體代碼), setTimeout, setInterval, setImmediate, I/O, UI rendering)。

一個settled狀態(tài)的promise(直接調(diào)用resolve或者reject)或者已經(jīng)變成settled狀態(tài)(異步請求被settled)的promise,會立刻將它的callback(then)放到microtask隊列里面。這就能保證promise的回調(diào)是異步的,即便promise已經(jīng)變?yōu)?b>settled狀態(tài)。因此一個已settledpromise調(diào)用.then(yey,nay)時將立即把一個microtask任務(wù)加入microtasks任務(wù)隊列。這就是為什么 promise1promise2script end 之后打印,因為正在運行的代碼必須在處理 microtasks 之前完成。promise1promise2setTimeout 之前打印,因為 microtasks 總是在下一個 task 之前執(zhí)行。

讓我們一步一步分析,(譯者注:跳轉(zhuǎn)到原文step by step示例,這對理解本文非常有用)

為什么在一些瀏覽器上的結(jié)果會有不同呢?

一些瀏覽器打印出來的結(jié)果是:script startscript endsetTimeoutpromise1promise2。這些瀏覽器在promise回調(diào)之前調(diào)用了setTimeout。這很可能是瀏覽器把promise回調(diào)當做是新任務(wù)(task )的一部分而不是微任務(wù)(microtask)。

這種錯誤某種程度上是可以被原諒的,因為promises規(guī)范來源于ECMAScript而不是HTML。ECMAScript定義了類似微任務(wù)的“jobs”概念,但是除了一些模糊的郵件討論之外,這種關(guān)系(jobs和microtasks)并不明確。但promises應(yīng)該作為微任務(wù)的一部分這是普遍的共識。

把promise當做是任務(wù)將會導(dǎo)致一些性能問題,回調(diào)可能沒有必要因為某些相關(guān)任務(wù)(比如渲染)而被延遲。由于與其他任務(wù)源的交互這也會導(dǎo)致一些不確定性,并且會中斷與其他Api的交互。

把promise歸類為微任務(wù)已經(jīng)是很急迫的事情了。Webkit(Safari內(nèi)核)一直都在做正確的事情,我想Safari最終會解決這和問題,事實上,F(xiàn)irefox43已經(jīng)修復(fù)了這個問題。

真正有趣的是,Safari和Firefox在這里都經(jīng)歷了一次回歸,從那以后問題就被修復(fù)了。我想知道這是不是一個巧合。

譯者注

task -> microtask -> ui render

對于promise而言,決議后(resolve或reject)才會把then回調(diào)推入microtaks隊列

參考

從Promise來看JavaScript中的Event Loop、Tasks和Microtasks

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

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

相關(guān)文章

  • 詳解JavaScript的任務(wù)任務(wù)隊列以及代碼執(zhí)行順序

    摘要:在微任務(wù)期間排隊的任何其他微任務(wù)都會被添加到隊列的末尾并進行處理。因此一個已的調(diào)用時將立即把一個微任務(wù)加入微任務(wù)隊列中。和回調(diào)被列為微任務(wù)。上述規(guī)則確保微任務(wù)不會中斷執(zhí)行中期的。 為了保證的可讀性,本文采用意譯而非直譯。 想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你! 思考下面 JavaScript 代碼: console.log(script start); ...

    rubyshen 評論0 收藏0
  • 今天,我明白了JS事件循環(huán)機制

    摘要:而這些隊列由的事件循環(huán)來搞定宏任務(wù)與微任務(wù),在最新標準中,它們被分別稱為與。我們梳理一下事件循環(huán)的執(zhí)行機制循環(huán)首先從宏任務(wù)開始,遇到,生成執(zhí)行上下文,開始進入執(zhí)行棧,可執(zhí)行代碼入棧,依次執(zhí)行代碼,調(diào)用完成出棧。 寫在前面 js是一門單線程的編程語言,也就是說js在處理任務(wù)的時候,所有任務(wù)只能在一個線程上排隊被執(zhí)行,那如果某一個任務(wù)耗時比較長呢?總不能等到它執(zhí)行結(jié)束再去執(zhí)行下一個。所以在...

    maochunguang 評論0 收藏0
  • JavaScript事件循環(huán)探索

    摘要:事件循環(huán)事件循環(huán)具有至少兩個隊列處理任務(wù)。同時含有宏任務(wù)和微任務(wù)主線程運行運行運行運行本例中在的事件處理函數(shù)里增加了一個立即兌現(xiàn)的,需要運行。處理的事件處理函數(shù)計時器主線程運行運行運行運行 一直對js的事件循環(huán)不是很清晰,最近看了JavaScript忍者秘籍的第13章后,有了一些感悟,特此總結(jié)一下,分享給大家。 單線程 眾所周知,JavaScript是單線程執(zhí)行模型,同一時刻只能執(zhí)行一...

    hqman 評論0 收藏0

發(fā)表評論

0條評論

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