日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

理解 async/await 的执行

發(fā)布時(shí)間:2025/7/14 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 理解 async/await 的执行 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這是一篇簡(jiǎn)單的短文章,方便理解。

開(kāi)局先丟官宣:sec-async-function-definitions?這個(gè)鏈接是對(duì) await 的解釋,解釋了它的執(zhí)行。

await 的執(zhí)行意味著(官宣巴拉巴拉地說(shuō)了14點(diǎn),這里簡(jiǎn)化成2點(diǎn)):

1. await 以 promise 形式完成,且 await 之后的代碼在 promise 被完成后以 .then 執(zhí)行。

2. 遇到 await 時(shí),將 async上下文 從上下文堆棧中移除,將上級(jí)(async之外)上下文(依次)恢復(fù)為當(dāng)前執(zhí)行的上下文;這步過(guò)程中需設(shè)置async上下文的評(píng)估狀態(tài),以便在恢復(fù)到執(zhí)行上下文時(shí)調(diào)用 await 之后的步驟。

第2點(diǎn)類(lèi)似的理解為 async上下文 被掛起,依次向上運(yùn)行上下文堆棧中的上下文代碼,完了后執(zhí)行 async 函數(shù)里 await 之后的代碼。

估計(jì)看的繞,用代碼說(shuō)話吧。

例一

console.log(1); async function async1(){ console.log(2); await async2(); console.log(3); };async function async2(){ console.log(4)};async1(); console.log(5);// 輸出結(jié)果 1 2 4 5 3

理解一下輸出結(jié)果:

第一步:輸出 1;

第二步:輸出 2,async1 先被調(diào)用,肯定優(yōu)先于函數(shù)內(nèi)的console和后面的console.log(5);

第三步:輸出 4,把 await async2() 轉(zhuǎn)為 promise 形式:

new Promise(resolve => {console.log('2')resolve();}).then(res => {// 抽出 await 之后的代碼放到.thenconsole.log(3);});

這時(shí)候先輸出 2,再等 3 的輸出。

但由于 3 在Promise規(guī)范里被設(shè)定為異步(劃重點(diǎn): ES6中屬microTask ,此處直接影響低版本中對(duì)promise實(shí)現(xiàn)的shim ),且await表示遇到await關(guān)鍵字后先將這塊代碼的asyncContext掛起并執(zhí)行上級(jí)上下文,所以先執(zhí)行了5,于是...

第四步:輸出 5,執(zhí)行完后回到 async context,再于是...

第五步:最后輸出 3。

例二

在官宣上沒(méi)看到? 依次向上??字樣鴨,咋肥事?繼續(xù)代碼:

console.log(1); function fn1(){function fn2(){async function async1(){ console.log(2);await fn3();console.log(3);}function fn3(){ console.log(4); }async1();new Promise(resolve => resolve(5)).then(res => console.log(res));console.log(6);}fn2();console.log(7); } fn1(); console.log(8); // 輸出結(jié)果 1 2 4 6 7 8 3 5

理解一下輸出結(jié)果:

第一步:輸出 1;

第二步:fn1 被執(zhí)行,fn2 被執(zhí)行,輸出 2;

第三步:fn3 被執(zhí)行,如第一例所述,輸出 4;

第四步:async context 被掛起,將 fn2 上下文作為運(yùn)行上下文,輸出 6;

第五步:fn2 上下文處理后繼續(xù)向外更新,fn1 上下文作為運(yùn)行上下文,輸出 7;

第六步:重復(fù)上述,輸出 8;

第七步:由于 fn3 的await(promise)在 fn2 中的 new Promise 前被加入執(zhí)行列隊(duì),根據(jù)先進(jìn)先出的執(zhí)行順序,輸出 3;

第八步:最后輸出 5。

例三

如果2個(gè) async 嵌套順序是啥樣的呢?再看代碼:

console.log(1); function fn1(){async function fn2(){async function async1(){ console.log(2);await fn3();console.log(3);}function fn3(){ console.log(4); }await async1();new Promise(resolve => resolve(5)).then(res => console.log(res));console.log(6);}fn2();console.log(7); } fn1(); console.log(8); // 1 2 4 7 8 3 6 5

重復(fù)上一個(gè)理解的過(guò)程,把 await async1(); 后的代碼放到最后執(zhí)行,看做:

new Promise(resolve => {// async1 里的代碼 resolve(); }).then(res => {new Promise(resolve => resolve(5)).then(res => console.log(res));console.log(6); });

對(duì)比以上輸出結(jié)果,正確!

如果有多個(gè)或者嵌套promise,則以??await 變成promise并掛起async上下文等上級(jí)上下文執(zhí)行完后恢復(fù)? 和? 事件的執(zhí)行順序遵循先進(jìn)先出? 兩個(gè)規(guī)則去完成推斷執(zhí)行順序。

注意

1. 在低版本瀏覽器中,async/await也有存在一些執(zhí)行順序的偏差(或者根本就不支持);

2. 在ES6和ES5中promise的執(zhí)行也有不同點(diǎn)(上述提到,ES6中promise屬microtask;在ES5中,暫未接觸到有api直接操作microtask的,所以.then的異步是用setTimeout代替,屬macrotask,導(dǎo)致輸出有差異);關(guān)于promise也可參考上文?分步理解 Promise 的實(shí)現(xiàn)

3. 由于客戶端環(huán)境不可控性太高,建議用于nodejs端開(kāi)發(fā)。

彩蛋

通過(guò)上面的理解,再看下面的圖片(這是koa middleware的... 嘿嘿嘿):

?

希望這篇筆記能夠幫助前端袍澤們對(duì)async await的執(zhí)行過(guò)程有更好的理解。上述內(nèi)容僅供參考,如有理解不當(dāng)?shù)牡胤?#xff0c;還望提出!

總結(jié)

以上是生活随笔為你收集整理的理解 async/await 的执行的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。