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

資訊專欄INFORMATION COLUMN

JavaScript同步、異步及事件循環(huán)

zr_hebo / 1717人閱讀

摘要:同步異步是單線程的,每次只能做一件事情。像以下這種情況,代碼會(huì)按順序執(zhí)行,這個(gè)就叫同步。雖然是單線程,但是瀏覽器是多線程的,在遇到像事件等這種任務(wù)時(shí),會(huì)轉(zhuǎn)交給瀏覽器的其他工作線程上面提到的幾個(gè)線程執(zhí)行,執(zhí)行完之后將回調(diào)函數(shù)放入到任務(wù)隊(duì)列。

同步、異步

JS是單線程的,每次只能做一件事情。像以下這種情況,代碼會(huì)按順序執(zhí)行,這個(gè)就叫同步。

console.log(1);
console.log(2);
console.log(3);

以下代碼會(huì)輸出2、3、1,像這種不按順序執(zhí)行的,或者說(shuō)代碼執(zhí)行中間有時(shí)間間隙的,叫異步。

setTimeout(() => {
    console.log(1);
}, 0);
console.log(2);
console.log(3);
事件循環(huán)

一個(gè)瀏覽器通常有以下幾個(gè)常駐的線程:

渲染引擎線程:該線程負(fù)責(zé)頁(yè)面的渲染

JS引擎線程:負(fù)責(zé)JS的解析和執(zhí)行

定時(shí)觸發(fā)器線程:處理定時(shí)事件,比如setTimeout, setInterval

事件觸發(fā)線程:處理DOM事件

異步http請(qǐng)求線程:處理http請(qǐng)求

渲染線程和JS引擎線程是不能同時(shí)進(jìn)行的。也就是說(shuō)在執(zhí)行代碼時(shí),渲染會(huì)掛起;渲染DOM時(shí),代碼也不會(huì)執(zhí)行。
雖然JS是單線程,但是瀏覽器是多線程的,在遇到像setTimeout、DOM事件、ajax等這種任務(wù)時(shí),會(huì)轉(zhuǎn)交給瀏覽器的其他工作線程(上面提到的幾個(gè)線程)執(zhí)行,執(zhí)行完之后將回調(diào)函數(shù)放入到任務(wù)隊(duì)列。

在JS運(yùn)行環(huán)境里,除了主線程外,還有任務(wù)隊(duì)列。

// eventLoop是一個(gè)用作隊(duì)列的數(shù)組
// (先進(jìn),先出)
var eventLoop = [ ];
var event;
// “永遠(yuǎn)”執(zhí)行
while (true) {
    // 一次tick
    if (eventLoop.length > 0) {
        // 拿到隊(duì)列中的下一個(gè)事件
        event = eventLoop.shift();
        // 現(xiàn)在,執(zhí)行下一個(gè)事件
        event();
    }
}

我們可以用上面的代碼來(lái)想像一下JS的執(zhí)行情況。

JS主線程,就像是一個(gè)while循環(huán),會(huì)一直執(zhí)行下去。在這期間,每次都會(huì)查看任務(wù)隊(duì)列有沒(méi)有需要執(zhí)行的任務(wù)(回調(diào)函數(shù))。在執(zhí)行完一個(gè)任務(wù)之后,會(huì)繼續(xù)下一個(gè)循環(huán),直到任務(wù)隊(duì)列所有任務(wù)都執(zhí)行完為止。

microtask(微任務(wù))、macrotask(宏任務(wù))

任務(wù)隊(duì)列又分微任務(wù)隊(duì)列和宏任務(wù)隊(duì)列

微任務(wù)

Promise

MutationObserver

Object.observe()(已廢棄)

宏任務(wù)

setTimeout

setInterval

setImmediate

IO

UI rendering(DOM event)

執(zhí)行過(guò)程

在JS執(zhí)行完同步任務(wù)之后,會(huì)開(kāi)始執(zhí)行微任務(wù)隊(duì)列

在將所有的微任務(wù)執(zhí)行完之后,會(huì)開(kāi)始執(zhí)行宏任務(wù)隊(duì)列

在執(zhí)行完一個(gè)宏任務(wù)之后,跳出來(lái),重新開(kāi)始下一個(gè)循環(huán)(從1開(kāi)始執(zhí)行)

也就是說(shuō)執(zhí)行微任務(wù)隊(duì)列 會(huì)將隊(duì)列中的所有微任務(wù)執(zhí)行完 而執(zhí)行宏任務(wù)隊(duì)列 每次只執(zhí)行一個(gè)宏任務(wù) 然后重新開(kāi)始下一個(gè)循環(huán)
我們可以看看以下代碼

setTimeout(() => {
    console.log(3)
    new Promise((resolve, reject) => {
        console.log(5)
        resolve()
    }).then(console.log(6))
}, 0)

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

new Promise((resolve, reject) => {
    console.log(1)
    resolve()
}).then(console.log(2))

輸出是1 2 3 5 6 4

我們來(lái)分析一下代碼的執(zhí)行過(guò)程

前面的兩個(gè)setTimeout都是宏任務(wù),所以現(xiàn)在宏任務(wù)隊(duì)列有2個(gè)任務(wù)

Promise里面的代碼是同步任務(wù),所以現(xiàn)在會(huì)馬上執(zhí)行 輸出1

Promise的then是微任務(wù),所以現(xiàn)在微任務(wù)隊(duì)列有1個(gè)任務(wù)

在執(zhí)行完同步任務(wù)之后,開(kāi)始執(zhí)行微任務(wù),也就是console.log(2), 輸出2

在執(zhí)行完微任務(wù)之后,會(huì)執(zhí)行宏任務(wù),第一個(gè)宏任務(wù)也就是第一個(gè)setTimeout

第一個(gè)setTimeout會(huì)先輸出3,然后輸出5,因?yàn)檫@兩個(gè)都是同步任務(wù),然后遇到then,加入微任務(wù)隊(duì)列,宏任務(wù)執(zhí)行完重新開(kāi)始下一個(gè)循環(huán)。

因?yàn)闆](méi)有同步代碼,所以接著執(zhí)行微任務(wù),此時(shí)微任務(wù)隊(duì)列有1個(gè)任務(wù)(第6步加入), 宏任務(wù)隊(duì)列還有1個(gè)任務(wù)(第6步執(zhí)行完了第一個(gè)宏任務(wù))

執(zhí)行微任務(wù),輸出6

再執(zhí)行宏任務(wù),輸出4

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

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

相關(guān)文章

  • 淺析JavaScript異步

    摘要:回調(diào)函數(shù),一般在同步情境下是最后執(zhí)行的,而在異步情境下有可能不執(zhí)行,因?yàn)槭录](méi)有被觸發(fā)或者條件不滿足。同步方式請(qǐng)求異步同步請(qǐng)求當(dāng)請(qǐng)求開(kāi)始發(fā)送時(shí),瀏覽器事件線程通知主線程,讓線程發(fā)送數(shù)據(jù)請(qǐng)求,主線程收到 一直以來(lái)都知道JavaScript是一門(mén)單線程語(yǔ)言,在筆試過(guò)程中不斷的遇到一些輸出結(jié)果的問(wèn)題,考量的是對(duì)異步編程掌握情況。一般被問(wèn)到異步的時(shí)候腦子里第一反應(yīng)就是Ajax,setTimse...

    Tangpj 評(píng)論0 收藏0
  • JavaScript 工作原理之四-事件循環(huán)異步編程的出現(xiàn)和 5 種更好的 async/await

    摘要:函數(shù)會(huì)在之后的某個(gè)時(shí)刻觸發(fā)事件定時(shí)器。事件循環(huán)中的這樣一次遍歷被稱為一個(gè)。執(zhí)行完畢并出棧。當(dāng)定時(shí)器過(guò)期,宿主環(huán)境會(huì)把回調(diào)函數(shù)添加至事件循環(huán)隊(duì)列中,然后,在未來(lái)的某個(gè)取出并執(zhí)行該事件。 原文請(qǐng)查閱這里,略有改動(dòng)。 本系列持續(xù)更新中,Github 地址請(qǐng)查閱這里。 這是 JavaScript 工作原理的第四章。 現(xiàn)在,我們將會(huì)通過(guò)回顧單線程環(huán)境下編程的弊端及如何克服這些困難以創(chuàng)建令人驚嘆...

    maochunguang 評(píng)論0 收藏0
  • (轉(zhuǎn))JavaScript同步、異步事件循環(huán)

    摘要:事件循環(huán)事件循環(huán)是指主線程重復(fù)從消息隊(duì)列中取消息執(zhí)行的過(guò)程。事件觸發(fā)時(shí),表示異步任務(wù)完成,會(huì)將事件監(jiān)聽(tīng)器函數(shù)封裝成一條消息放到消息隊(duì)列中,等待主線程執(zhí)行。 一. 單線程 我們常說(shuō)JavaScript是單線程的。 所謂單線程,是指在JS引擎中負(fù)責(zé)解釋和執(zhí)行JavaScript代碼的線程只有一個(gè)。不妨叫它主線程。 但是實(shí)際上還存在其他的線程。例如:處理AJAX請(qǐng)求的線程、處理DOM事件的線...

    android_c 評(píng)論0 收藏0
  • js的單線程,異步回調(diào)函數(shù)

    摘要:當(dāng)主線程開(kāi)始執(zhí)行異步任務(wù),實(shí)際就是執(zhí)行對(duì)應(yīng)的回調(diào)函數(shù)。異步任務(wù)必須指定回調(diào)函數(shù)。所以注意的是,只是將事件插入了任務(wù)隊(duì)列,必須等到當(dāng)前代碼執(zhí)行棧執(zhí)行完,主線程才會(huì)去執(zhí)行它指定的回調(diào)函數(shù)。 最近本人對(duì)于js的運(yùn)行機(jī)制,特別是異步,還有回調(diào)函數(shù)感覺(jué)很亂,于是參考了很多有用的博客(博客原文地址會(huì)在文末給出),整理如下: js單線程 我們都知道,Javascript語(yǔ)言的執(zhí)行環(huán)境是單線程(si...

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

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

0條評(píng)論

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