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

資訊專欄INFORMATION COLUMN

學(xué)習(xí)JavaScript異步、事件循環(huán)

nemo / 1187人閱讀

摘要:使用關(guān)鍵字來(lái)表示,在函數(shù)內(nèi)部使用來(lái)表示異步。執(zhí)行完了后,執(zhí)行棧再次為空,事件觸發(fā)線程會(huì)重復(fù)上一步操作,再取出一個(gè)消息隊(duì)列中的任務(wù),這種機(jī)制就被稱為事件循環(huán)機(jī)制。

async 函數(shù)是 Generator 函數(shù)的語(yǔ)法糖。使用 關(guān)鍵字 async 來(lái)表示,在函數(shù)內(nèi)部使用 await 來(lái)表示異步。想較于 Generator,Async 函數(shù)的改進(jìn)在于下面四點(diǎn):

內(nèi)置執(zhí)行器 Generator 函數(shù)的執(zhí)行必須依靠執(zhí)行器,而 Aysnc 函數(shù)自帶執(zhí)行器,調(diào)用方式跟普通函數(shù)的調(diào)用一樣

更好的語(yǔ)義 async 和 await 相較于 * 和 yield 更加語(yǔ)義化

更廣的適用性 co 模塊約定,yield 命令后面只能是Thunk 函數(shù)或 Promise對(duì)象。而 async 函數(shù)的 await 命令后面則可以是 Promise 或者原始類型的值(Number,string,boolean,但這時(shí)等同于同步操作)

返回值是 Promise async 函數(shù)返回值是 Promise 對(duì)象,比 Generator 函數(shù)返回的 Iterator 對(duì)象方便,可以直接使用 then() 方法進(jìn)行調(diào)用

await命令:正常情況下,await命令后面是一個(gè) Promise 對(duì)象,返回該對(duì)象的結(jié)果。如果不是 Promise 對(duì)象,就直接返回對(duì)應(yīng)的值

下面給大家看一道之前看過(guò)的題:

function test1() {
    console.log("執(zhí)行test1");
    return "test1";
}

 function test2() {
    console.log("執(zhí)行test2");
    return Promise.resolve("hello test2");
}

async function asyncTest() {
    console.log("asyncTest start...");
    const v1 = await test1();
    console.log(v1);
    const v2 = await test2();
    console.log(v2);
    console.log(v1, v2);
}

setTimeout(function(){
    console.log("setTimeout")
},0)  

asyncTest();


new Promise(function(resolve){
    console.log("promise1")
    resolve();
}).then(function(){
    console.log("promise2")
})
console.log("test end")

這道題結(jié)合了setTimeout、async、promise異步函數(shù),根據(jù)三種不同異步任務(wù)執(zhí)行順序可以學(xué)習(xí)js引擎的事件循環(huán)機(jī)制,咱們先看下結(jié)果:

test start...
執(zhí)行test1
promise1
test end
test1
執(zhí)行test2
promise2
hello test2
test1,hello test2
setTimeout

再講答案之前先理解以下幾個(gè)概念:

事件循環(huán)與消息隊(duì)列

JS引擎線程遇到異步(DOM事件監(jiān)聽(tīng)、網(wǎng)絡(luò)請(qǐng)求、setTimeout計(jì)時(shí)器等...),會(huì)交給相應(yīng)的線程多帶帶去維護(hù)異步任務(wù),等待某個(gè)時(shí)機(jī)(計(jì)時(shí)器結(jié)束、網(wǎng)絡(luò)請(qǐng)求成功、用戶點(diǎn)擊DOM),然后由 事件觸發(fā)線程 將異步對(duì)應(yīng)的 回調(diào)函數(shù) 加入到消息隊(duì)列中,消息隊(duì)列中的回調(diào)函數(shù)等待被執(zhí)行。

同時(shí),JS引擎線程會(huì)維護(hù)一個(gè) 執(zhí)行棧,同步代碼會(huì)依次加入執(zhí)行棧然后執(zhí)行,結(jié)束會(huì)退出執(zhí)行棧。

如果執(zhí)行棧里的任務(wù)執(zhí)行完成,即執(zhí)行棧為空的時(shí)候(即JS引擎線程空閑),事件觸發(fā)線程才會(huì)從消息隊(duì)列取出一個(gè)任務(wù)(即異步的回調(diào)函數(shù))放入執(zhí)行棧中執(zhí)行。

消息隊(duì)列是類似隊(duì)列的數(shù)據(jù)結(jié)構(gòu),遵循**先入先出(FIFO)**的規(guī)則。

執(zhí)行完了后,執(zhí)行棧再次為空,事件觸發(fā)線程會(huì)重復(fù)上一步操作,再取出一個(gè)消息隊(duì)列中的任務(wù),這種機(jī)制就被稱為事件循環(huán)(event loop)機(jī)制。

主代碼塊(script)依次加入執(zhí)行棧,依次執(zhí)行,主代碼塊為:

setTimeout()

asyncTest()

Promise()

console.log("test end")

宏任務(wù)與微任務(wù)

macrotask(宏任務(wù)) :主代碼塊、setTimeout、setInterval等(可以看到,事件隊(duì)列中的每一個(gè)事件都是一個(gè) macrotask,現(xiàn)在稱之為宏任務(wù)隊(duì)列

和 microtask(微任務(wù)):Promise、process.nextTick等

JS引擎線程首先執(zhí)行主代碼塊。
每次執(zhí)行棧執(zhí)行的代碼就是一個(gè)宏任務(wù),包括任務(wù)隊(duì)列(宏任務(wù)隊(duì)列)中的,因?yàn)閳?zhí)行棧中的宏任務(wù)執(zhí)行完會(huì)去取任務(wù)隊(duì)列(宏任務(wù)隊(duì)列)中的任務(wù)加入執(zhí)行棧中,即同樣是事件循環(huán)的機(jī)制。
在執(zhí)行宏任務(wù)時(shí)遇到Promise等,會(huì)創(chuàng)建微任務(wù)(.then()里面的回調(diào)),并加入到微任務(wù)隊(duì)列隊(duì)尾。
microtask必然是在某個(gè)宏任務(wù)執(zhí)行的時(shí)候創(chuàng)建的,而在下一個(gè)宏任務(wù)開(kāi)始之前,瀏覽器會(huì)對(duì)頁(yè)面重新渲染(task >> 渲染 >> 下一個(gè)task(從任務(wù)隊(duì)列中取一個(gè)))。同時(shí),在上一個(gè)宏任務(wù)執(zhí)行完成后,渲染頁(yè)面之前,會(huì)執(zhí)行當(dāng)前微任務(wù)隊(duì)列中的所有微任務(wù)。
也就是說(shuō),在某一個(gè)macrotask執(zhí)行完后,在重新渲染與開(kāi)始下一個(gè)宏任務(wù)之前,就會(huì)將在它執(zhí)行期間產(chǎn)生的所有microtask都執(zhí)行完畢(在渲染前)。

執(zhí)行機(jī)制:

執(zhí)行一個(gè)宏任務(wù)(棧中沒(méi)有就從事件隊(duì)列中獲取)

執(zhí)行過(guò)程中如果遇到微任務(wù),就將它添加到微任務(wù)的任務(wù)隊(duì)列中

宏任務(wù)執(zhí)行完畢后,立即執(zhí)行當(dāng)前微任務(wù)隊(duì)列中的所有微任務(wù)(依次執(zhí)行)

當(dāng)前宏任務(wù)執(zhí)行完畢,開(kāi)始檢查渲染,然后GUI線程接管渲染

渲染完畢后,JS引擎線程繼續(xù),開(kāi)始下一個(gè)宏任務(wù)(從宏任務(wù)隊(duì)列中獲?。?/p>

遇到異步函數(shù) setTimeout,交給定時(shí)器觸發(fā)線程 setTimeout加入宏任務(wù)隊(duì)列,JS引擎線程繼續(xù),出棧;

執(zhí)行異步函數(shù)asyncTest,首先打印test start...

執(zhí)行await test1函數(shù)首先打印"執(zhí)行test1",await讓出線程去執(zhí)行后面的代碼;

執(zhí)行Promise 首先打印promise1,then后面函數(shù)為微任務(wù),添加到微任務(wù)隊(duì)列中

JS引擎線程繼續(xù)向下執(zhí)行同步代碼console.log("test end")打印"test end"

回到asyncTest執(zhí)行await test1由于返回不是promise對(duì)象,所以直接返回test1

執(zhí)行await test2()同樣先打印 "執(zhí)行test2",由于test2返回promise對(duì)象 會(huì)加入到之前微任務(wù)隊(duì)列中,await繼續(xù)讓出

執(zhí)行微任務(wù)隊(duì)列,由于任務(wù)隊(duì)列遵循先進(jìn)先出結(jié)果,所以首先打印promise2,然后打印hello test2

微任務(wù)隊(duì)列執(zhí)行完成后繼續(xù)執(zhí)行asyncTest內(nèi) await之后的代碼打印 倆個(gè)await返回的值 --test1,hello test2

最后回到宏任務(wù)隊(duì)列執(zhí)行setTimeout,打印setTimeout

如果我把test1變成異步函數(shù),大家再思考一下會(huì)打印什么結(jié)果:

async  function test1() {
    console.log("執(zhí)行test1");
    return "test1";
}

 function test2() {
    console.log("執(zhí)行test2");
    return Promise.resolve("hello test2");
}

async function asyncTest() {
    console.log("asyncTest start...");
    const v1 = await test1();
    console.log(v1);
    const v2 = await test2();
    console.log(v2);
    console.log(v1, v2);
}

setTimeout(function(){
    console.log("setTimeout")
},0)  

asyncTest();


new Promise(function(resolve){
    console.log("promise1")
    resolve();
}).then(function(){
    console.log("promise2")
})
console.log("test end")

以上就是此代碼執(zhí)行過(guò)程,由于本人也是在學(xué)習(xí)總結(jié)中,如有不對(duì)的地方請(qǐng)指教,共同學(xué)習(xí),一起進(jìn)步?。?!

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

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

相關(guān)文章

  • 理解異步JavaScript

    摘要:當(dāng)函數(shù)結(jié)束,將會(huì)被從調(diào)用棧移出。事件循環(huán)事件循環(huán)的責(zé)任就是查看調(diào)用棧并確定調(diào)用棧是否為空。事件循環(huán)會(huì)再次檢查調(diào)用棧是否為空,如果為空的話,它會(huì)把事件回調(diào)壓入棧中,然后回調(diào)函數(shù)則被執(zhí)行。 寫(xiě)在文章前 這篇文章是翻譯自Sukhjinder Arora的Understanding Asynchronous JavaScript。這篇文章描述了異步和同步JavaScript是如何在運(yùn)行環(huán)境中,...

    ixlei 評(píng)論0 收藏0
  • Javascript 事件循環(huán)event loop

    摘要:現(xiàn)實(shí)中是這樣的執(zhí)行結(jié)果為結(jié)果告訴我們,是單線程沒(méi)錯(cuò),不過(guò)不是逐行同步執(zhí)行。搜索了很多官方個(gè)人博客得到了一堆詞引擎主線程事件表事件隊(duì)列宏任務(wù)微任務(wù),徹底懵逼。。。以此規(guī)則不停的執(zhí)行下去就是我們所聽(tīng)到的事件循環(huán)。 都知道javascript是單線程,那么問(wèn)題來(lái)了,既然是單線程順序執(zhí)行,那怎么做到異步的呢? 我們理解的單線程應(yīng)該是這樣的,排著一個(gè)個(gè)來(lái),是同步執(zhí)行。 showImg(https...

    Miyang 評(píng)論0 收藏0
  • 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制

    摘要:事件完成,回調(diào)函數(shù)進(jìn)入。主線程從讀取回調(diào)函數(shù)并執(zhí)行。終于執(zhí)行完了,終于從進(jìn)入了主線程執(zhí)行。遇到,立即執(zhí)行。宏任務(wù)微任務(wù)第三輪事件循環(huán)宏任務(wù)執(zhí)行結(jié)束,執(zhí)行兩個(gè)微任務(wù)和。事件循環(huán)事件循環(huán)是實(shí)現(xiàn)異步的一種方法,也是的執(zhí)行機(jī)制。 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果讀完本文還不懂,可以揍我。不論你是javascript新手還是老鳥(niǎo),不論是面試求職,還是日常開(kāi)發(fā)工作...

    dreambei 評(píng)論0 收藏0
  • 事件循環(huán)機(jī)制

    摘要:事件觸發(fā)線程主要負(fù)責(zé)將準(zhǔn)備好的事件交給引擎線程執(zhí)行。進(jìn)程瀏覽器渲染進(jìn)程瀏覽器內(nèi)核,主要負(fù)責(zé)頁(yè)面的渲染執(zhí)行以及事件的循環(huán)。第二輪循環(huán)結(jié)束。 將自己讀到的比較好的文章分享出來(lái),大家互相學(xué)習(xí),各位大佬有好的文章也可以留個(gè)鏈接互相學(xué)習(xí),萬(wàn)分感謝! 線程與進(jìn)程 關(guān)于線程與進(jìn)程的關(guān)系可以用下面的圖進(jìn)行說(shuō)明: showImg(https://segmentfault.com/img/bVbjSZt?...

    Blackjun 評(píng)論0 收藏0
  • 事件循環(huán)機(jī)制

    摘要:事件觸發(fā)線程主要負(fù)責(zé)將準(zhǔn)備好的事件交給引擎線程執(zhí)行。進(jìn)程瀏覽器渲染進(jìn)程瀏覽器內(nèi)核,主要負(fù)責(zé)頁(yè)面的渲染執(zhí)行以及事件的循環(huán)。第二輪循環(huán)結(jié)束。 將自己讀到的比較好的文章分享出來(lái),大家互相學(xué)習(xí),各位大佬有好的文章也可以留個(gè)鏈接互相學(xué)習(xí),萬(wàn)分感謝! 線程與進(jìn)程 關(guān)于線程與進(jìn)程的關(guān)系可以用下面的圖進(jìn)行說(shuō)明: showImg(https://segmentfault.com/img/bVbjSZt?...

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

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

0條評(píng)論

nemo

|高級(jí)講師

TA的文章

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