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

資訊專欄INFORMATION COLUMN

JS異步詳解 - 瀏覽器/Node/事件循環(huán)/消息隊(duì)列/宏任務(wù)/微任務(wù)

awesome23 / 1751人閱讀

js異步歷史

一個(gè) JavaScript 引擎會(huì)常駐于內(nèi)存中,它等待著我們把JavaScript 代碼或者函數(shù)傳遞給它執(zhí)行

在 ES3 和更早的版本中,JavaScript 本身還沒(méi)有異步執(zhí)行代碼的能力,引擎就把代碼直接順次執(zhí)行了,異步任務(wù)都是宿主環(huán)境(瀏覽器)發(fā)起的(setTimeout、AJAX等)。

在 ES5 之后,JavaScript 引入了 Promise,這樣,不需要瀏覽器的安排,JavaScript 引擎本身也可以發(fā)起任務(wù)了

JS異步實(shí)現(xiàn)原理

js為單線程,js引擎中負(fù)責(zé)解析執(zhí)行js代碼的線程只有一個(gè)(主線程),即每次只能做一件事,其他IO操作放入任務(wù)隊(duì)列等待執(zhí)行,異步過(guò)程中,工作線程異步操作完成后需要通知主線程。那么這個(gè)通知機(jī)制是利用消息隊(duì)列事件循環(huán)(EventLoop)實(shí)際上,主線程只會(huì)做一件事情,就是從消息隊(duì)列里面取消息、執(zhí)行消息,再取消息、再執(zhí)行。當(dāng)消息隊(duì)列為空時(shí),就會(huì)等待直到消息隊(duì)列變成非空。而且主線程只有在將當(dāng)前的消息執(zhí)行完成后,才會(huì)去取下一個(gè)消息
node:node.js單線程只是一個(gè)js主線程,本質(zhì)上的異步操作還是由線程池完成的,node將所有的阻塞操作都交給了內(nèi)部的線程池去實(shí)現(xiàn),本身只負(fù)責(zé)不斷的往返調(diào)度,并沒(méi)有進(jìn)行真正的I/O操作,從而實(shí)現(xiàn)異步非阻塞I/O,這便是node單線程的精髓之處了。

瀏覽器 概念

消息隊(duì)列:消息隊(duì)列是一個(gè)先進(jìn)先出的隊(duì)列,它里面存放著各種消息。

事件循環(huán):事件循環(huán)是指主線程重復(fù)從消息隊(duì)列中取消息、執(zhí)行的過(guò)程。(瀏覽器至少有一個(gè)事件循環(huán),一個(gè)事件循環(huán)至少有一個(gè)任務(wù)隊(duì)列(macrotask))

微任務(wù):

JavaScript 引擎發(fā)起的任務(wù) - JS 引擎級(jí)別

promise回調(diào),MutationObserver,process.nextTick,Object.observe

宏任務(wù)

宿主發(fā)起的任務(wù),每次的一段js代碼執(zhí)行過(guò)程,其實(shí)都是一個(gè)宏觀任務(wù) - 宿主級(jí)別

整體的js代碼,事件回調(diào),XHR回調(diào),定時(shí)器(setTimeout/setInterval/setImmediate),IO操作,UI render

宏任務(wù)和微任務(wù)關(guān)系:每個(gè)macro宏任務(wù)會(huì)維護(hù)一個(gè)micro微任務(wù)列表

事件循環(huán)過(guò)程

首先我們分析有多少個(gè)宏任務(wù);

在每個(gè)宏任務(wù)中,分析有多少個(gè)微任務(wù);

根據(jù)調(diào)用次序,確定宏任務(wù)中的微任務(wù)執(zhí)行次序;

根據(jù)宏任務(wù)的觸發(fā)規(guī)則和調(diào)用次序,確定宏任務(wù)的執(zhí)行次序;

確定整個(gè)順序

視圖渲染時(shí)機(jī):

本輪事件循環(huán)的microtask隊(duì)列被執(zhí)行完之后(不是每輪事件循環(huán)都會(huì)執(zhí)行視圖更新,瀏覽器有自己的優(yōu)化策略)

注意:執(zhí)行任務(wù)的耗時(shí)會(huì)影響視圖渲染的時(shí)機(jī)。通常瀏覽器以每秒60幀(60fps)的速率刷新頁(yè)面(16.7ms渲染一幀)所以如果要讓用戶覺(jué)得順暢,單個(gè)macrotask及它相關(guān)的所有microtask最好能在16.7ms內(nèi)完成。

Node 概念

非阻塞 I/O 操作:盡管 JavaScript 是單線程處理的——當(dāng)有可能的時(shí)候,它們會(huì)把操作轉(zhuǎn)移到系統(tǒng)內(nèi)核中去,當(dāng)其中的一個(gè)操作完成的時(shí)候,內(nèi)核通知 Node.js 將適合的回調(diào)函數(shù)添加到 輪詢 隊(duì)列中等待時(shí)機(jī)執(zhí)行

事件循環(huán)過(guò)程

過(guò)程

event loop 的每個(gè)階段都有一個(gè)任務(wù)隊(duì)列(一個(gè) FIFO 隊(duì)列來(lái)執(zhí)行回調(diào))

當(dāng) event loop 到達(dá)某個(gè)階段時(shí),將執(zhí)行該階段的任務(wù)隊(duì)列,直到隊(duì)列清空或執(zhí)行的回調(diào)達(dá)到系統(tǒng)上限后,才會(huì)轉(zhuǎn)入下一個(gè)階段

當(dāng)所有階段被順序執(zhí)行一次后,稱 event loop 完成了一個(gè) tick

每次事件循環(huán)都包含了6個(gè)階段

timers 階段:這個(gè)階段執(zhí)行timer(setTimeoutsetInterval)的回調(diào)

I/O callbacks 階段:執(zhí)行一些系統(tǒng)調(diào)用錯(cuò)誤,比如網(wǎng)絡(luò)通信的錯(cuò)誤回調(diào)

idle, prepare 階段:僅node內(nèi)部使用

poll 階段:獲取新的I/O事件, 適當(dāng)?shù)臈l件下node將阻塞在這里

check 階段:執(zhí)行 setImmediate() 的回調(diào)

close callbacks 階段:執(zhí)行 socketclose 事件回調(diào)

timers 階段

Node 會(huì)去檢查有無(wú)已過(guò)期的timer,如果有則把它的回調(diào)壓入timer的任務(wù)隊(duì)列中等待執(zhí)行

技術(shù)上來(lái)說(shuō),poll 階段控制 timers 什么時(shí)候執(zhí)行。

poll 階段

poll 階段主要有2個(gè)功能:

處理 poll 隊(duì)列的事件

當(dāng)有已超時(shí)的 timer,執(zhí)行它的回調(diào)函數(shù)

執(zhí)行過(guò)程:當(dāng)event loop進(jìn)入 poll 階段,并且 沒(méi)有設(shè)定的timers(there are no timers scheduled),會(huì)發(fā)生下面兩件事之一:

如果 poll 隊(duì)列不空,event loop會(huì)遍歷隊(duì)列并同步執(zhí)行回調(diào),直到隊(duì)列清空或執(zhí)行的回調(diào)數(shù)到達(dá)系統(tǒng)上限;

如果 poll 隊(duì)列為空,則發(fā)生以下兩件事之一:

如果代碼已經(jīng)被setImmediate()設(shè)定了回調(diào), event loop將結(jié)束 poll 階段進(jìn)入 check 階段來(lái)執(zhí)行 check 隊(duì)列(里的回調(diào))。

如果代碼沒(méi)有被setImmediate()設(shè)定回調(diào),event loop將阻塞在該階段等待回調(diào)被加入 poll 隊(duì)列,并立即執(zhí)行。

當(dāng)event loop進(jìn)入 poll 階段,并且 有設(shè)定的timers,一旦 poll 隊(duì)列為空(poll 階段空閑狀態(tài)): event loop將檢查timers,如果有1個(gè)或多個(gè)timers的下限時(shí)間已經(jīng)到達(dá),event loop將繞回 timers 階段,并執(zhí)行 timer隊(duì)列。

注意:沒(méi)有setImmediate()會(huì)導(dǎo)致event loop阻塞在poll階段,這樣之前設(shè)置的timer豈不是執(zhí)行不了了?所以咧,在poll階段event loop會(huì)有一個(gè)檢查機(jī)制,檢查timer隊(duì)列是否為空,如果timer隊(duì)列非空,event loop就開(kāi)始下一輪事件循環(huán),即重新進(jìn)入到timer階段。

process.nextTick() VS setImmediate()

process.nextTick()

在各個(gè)事件階段之間執(zhí)行,一旦執(zhí)行,要直到nextTick隊(duì)列被清空,才會(huì)進(jìn)入到下一個(gè)事件階段

遞歸調(diào)用 process.nextTick(),會(huì)導(dǎo)致出現(xiàn)I/O starving(饑餓)

setImmediate

對(duì)比
setTimeout(()=>{
    console.log("timer1")

    Promise.resolve().then(function() {
        console.log("promise1")
    })
}, 0)

setTimeout(()=>{
    console.log("timer2")

    Promise.resolve().then(function() {
        console.log("promise2")
    })
}, 0)

//瀏覽器:
timer1
promise1
timer2
promise2

// node
timer1
timer2
promise1
promise2

http://lynnelv.github.io/img/...

http://lynnelv.github.io/img/...

補(bǔ)充閱讀

node單線程底層實(shí)現(xiàn)機(jī)制:

https://juejin.im/post/5b61d8...

https://yq.aliyun.com/article...

https://juejin.im/post/5b1e55...

node setTimeOut(), setInterval(), setImmediate() 以及 process.nextTick()區(qū)別

js 三種定時(shí)器的區(qū)別

https://www.cnblogs.com/onepi...

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

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

相關(guān)文章

  • 淺談不同環(huán)境下的JavaScript執(zhí)行機(jī)制 + 示例詳解

    摘要:如果沒(méi)有其他異步任務(wù)要處理比如到期的定時(shí)器,會(huì)一直停留在這個(gè)階段,等待請(qǐng)求返回結(jié)果。執(zhí)行的執(zhí)行事件關(guān)閉請(qǐng)求的,例如事件循環(huán)的每一次循環(huán)都需要依次經(jīng)過(guò)上述的階段。因此,才會(huì)早于執(zhí)行。 showImg(https://segmentfault.com/img/bVbnY76); 概念 同步任務(wù)(Synchronous) 在主線程上排隊(duì)執(zhí)行的任務(wù),只有前一個(gè)任務(wù)執(zhí)行完畢,才能執(zhí)行后一個(gè)任務(wù) ...

    wanghui 評(píng)論0 收藏0
  • 總結(jié):JavaScript異步事件循環(huán)消息隊(duì)列任務(wù)任務(wù)

    摘要:?jiǎn)尉€程異步非阻塞然后,這又牽扯到了事件循環(huán)消息隊(duì)列,還有微任務(wù)宏任務(wù)這些。此步的位置不確定某個(gè)時(shí)刻后,定時(shí)器觸發(fā)線程通知事件觸發(fā)線程,事件觸發(fā)線程將回調(diào)函數(shù)加入消息隊(duì)列隊(duì)尾,等待引擎線程執(zhí)行。 前言 Philip Roberts 在演講 great talk at JSConf on the event loop 中說(shuō):要是用一句話來(lái)形容 JavaScript,我可能會(huì)這樣: Java...

    qianfeng 評(píng)論0 收藏0
  • Js事件循環(huán)(Event Loop)機(jī)制以及實(shí)例講解

    摘要:主線程要明確的一點(diǎn)是,主線程跟執(zhí)行棧是不同概念,主線程規(guī)定現(xiàn)在執(zhí)行執(zhí)行棧中的哪個(gè)事件。主線程循環(huán)即主線程會(huì)不停的從執(zhí)行棧中讀取事件,會(huì)執(zhí)行完所有棧中的同步代碼。以上參考資料詳解中的事件循環(huán)機(jī)制中的事件循環(huán)運(yùn)行機(jī)制詳解再談 showImg(https://segmentfault.com/img/remote/1460000015317437?w=1920&h=1080); 前言 大家都...

    Anshiii 評(píng)論0 收藏0
  • JavaScript運(yùn)行機(jī)制和事件循環(huán)

    摘要:主線程不斷重復(fù)上面的三步,此過(guò)程也就是常說(shuō)的事件循環(huán)。所以主線程代碼執(zhí)行時(shí)間過(guò)長(zhǎng),會(huì)阻塞事件循環(huán)的執(zhí)行。參考資料這一次,徹底弄懂執(zhí)行機(jī)制任務(wù)隊(duì)列的順序機(jī)制事件循環(huán)搞懂異步事件輪詢與中的事件循環(huán) 1. 說(shuō)明 讀過(guò)本文章后,您能知道: JavaScript代碼在瀏覽器中的執(zhí)行機(jī)制和事件循環(huán) 面試中經(jīng)常遇到的代碼輸出順序問(wèn)題 首先通過(guò)一段代碼來(lái)驗(yàn)證你是否了解代碼輸出順序,如果你不知道輸出...

    Ververica 評(píng)論0 收藏0
  • JavaScript 運(yùn)行機(jī)制--Event Loop詳解

    摘要:上代碼代碼可以看出,不僅函數(shù)比指定的回調(diào)函數(shù)先執(zhí)行,而且函數(shù)也比先執(zhí)行。這是因?yàn)楹笠粋€(gè)事件進(jìn)入的時(shí)候,事件環(huán)可能處于不同的階段導(dǎo)致結(jié)果的不確定。這是因?yàn)橐驗(yàn)閳?zhí)行完后,程序設(shè)定了和,因此階段不會(huì)被阻塞進(jìn)而進(jìn)入階段先執(zhí)行,后進(jìn)入階段執(zhí)行。 JavaScript(簡(jiǎn)稱JS)是前端的首要研究語(yǔ)言,要想真正理解JavaScript就繞不開(kāi)他的運(yùn)行機(jī)制--Event Loop(事件環(huán)) JS是一門...

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

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

0條評(píng)論

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