久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      需要真正明白的Promise

      需要真正明白的Promise

      相關(guān)學(xué)習(xí)推薦:javascript學(xué)習(xí)教程

      Promise 關(guān)于 API 這塊大家應(yīng)該都能熟練使用,但是和微任務(wù)相關(guān)的你可能還存在知識(shí)盲區(qū)。

      前置知識(shí)

      在開始正文前,我們先把本文涉及到的一些內(nèi)容提前定個(gè)基調(diào)。

      Promise 哪些 API 涉及了微任務(wù)?

      Promise 中只有涉及到狀態(tài)變更后才需要被執(zhí)行的回調(diào)才算是微任務(wù),比如說 thencatch 、finally ,其他所有的代碼執(zhí)行都是宏任務(wù)(同步執(zhí)行)。

      需要真正明白的Promise

      上圖中藍(lán)色為同步執(zhí)行,黃色為異步執(zhí)行(丟到微任務(wù)隊(duì)列中)。

      這些微任務(wù)何時(shí)被加入微任務(wù)隊(duì)列?

      這個(gè)問題我們根據(jù) ecma 規(guī)范來看:

      • 如果此時(shí) Promise 狀態(tài)為 pending,那么成功或失敗的回調(diào)會(huì)分別被加入至 [[PromiseFulfillReactions]][[PromiseRejectReactions]] 中。如果你看過手寫 Promise 的代碼的話,應(yīng)該能發(fā)現(xiàn)有兩個(gè)數(shù)組存儲(chǔ)這些回調(diào)函數(shù)。

      • 如果此時(shí) Promise 狀態(tài)為非 pending 時(shí),回調(diào)會(huì)成為 Promise Jobs,也就是微任務(wù)。

      了解完以上知識(shí)后,正片開始。

      同一個(gè) then,不同的微任務(wù)執(zhí)行

      初級

      Promise.resolve()   .then(() => {    console.log("then1");    Promise.resolve().then(() => {      console.log("then1-1");     });   })   .then(() => {    console.log("then2");   });復(fù)制代碼

      以上代碼大家應(yīng)該都能得出正確的答案:then1 → then1-1 → then2。

      雖然 then 是同步執(zhí)行,并且狀態(tài)也已經(jīng)變更。但這并不代表每次遇到 then 時(shí)我們都需要把它的回調(diào)丟入微任務(wù)隊(duì)列中,而是等待 then 的回調(diào)執(zhí)行完畢后再根據(jù)情況執(zhí)行對應(yīng)操作。

      基于此,我們可以得出第一個(gè)結(jié)論:鏈?zhǔn)秸{(diào)用中,只有前一個(gè) then 的回調(diào)執(zhí)行完畢后,跟著的 then 中的回調(diào)才會(huì)被加入至微任務(wù)隊(duì)列。

      中級

      大家都知道了 Promise resolve 后,跟著的 then 中的回調(diào)會(huì)馬上進(jìn)入微任務(wù)隊(duì)列。

      那么以下代碼你認(rèn)為的輸出會(huì)是什么?

      let p = Promise.resolve();  p.then(() => {  console.log("then1");  Promise.resolve().then(() => {    console.log("then1-1");   }); }).then(() => {  console.log("then1-2"); });  p.then(() => {  console.log("then2"); });  復(fù)制代碼

      按照一開始的認(rèn)知我們不難得出 then2 會(huì)在 then1-1 后輸出,但是實(shí)際情況卻是相反的。

      基于此我們得出第二個(gè)結(jié)論:每個(gè)鏈?zhǔn)秸{(diào)用的開端會(huì)首先依次進(jìn)入微任務(wù)隊(duì)列。

      接下來我們換個(gè)寫法:

      let p = Promise.resolve().then(() => {  console.log("then1");  Promise.resolve().then(() => {    console.log("then1-1");   }); }).then(() => {  console.log("then2"); });  p.then(() => {  console.log("then3"); });復(fù)制代碼

      上述代碼其實(shí)有個(gè)陷阱,then 每次都會(huì)返回一個(gè)新的 Promise,此時(shí)的 p 已經(jīng)不是 Promise.resolve() 生成的,而是最后一個(gè) then 生成的,因此 then3 應(yīng)該是在 then2 后打印出來的。

      順便我們也可以把之前得出的結(jié)論優(yōu)化為:同一個(gè) Promise 的每個(gè)鏈?zhǔn)秸{(diào)用的開端會(huì)首先依次進(jìn)入微任務(wù)隊(duì)列。

      高級

      以下大家可以猜猜 then1-2 會(huì)在何時(shí)打印出來?

      Promise.resolve()   .then(() => {    console.log("then1");    Promise.resolve()       .then(() => {        console.log("then1-1");        return 1;       })       .then(() => {        console.log("then1-2");       });   })   .then(() => {    console.log("then2");   })   .then(() => {    console.log("then3");   })   .then(() => {    console.log("then4");   });復(fù)制代碼

      這題肯定是簡單的,記住第一個(gè)結(jié)論就能得出答案,以下是解析:

      • 第一次 resolve 后第一個(gè) then 的回調(diào)進(jìn)入微任務(wù)隊(duì)列并執(zhí)行,打印 then1

      • 第二次 resolve 后內(nèi)部第一個(gè) then 的回調(diào)進(jìn)入微任務(wù)隊(duì)列,此時(shí)外部第一個(gè) then 的回調(diào)全部執(zhí)行完畢,需要將外部的第二個(gè) then 回調(diào)也插入微任務(wù)隊(duì)列。

      • 執(zhí)行微任務(wù),打印 then1-1then2,然后分別再將之后 then 中的回調(diào)插入微任務(wù)隊(duì)列

      • 執(zhí)行微任務(wù),打印 then1-2then3 ,之后的內(nèi)容就不一一說明了

      接下來我們把 return 1 修改一下,結(jié)果可就大不相同啦:

      Promise.resolve()   .then(() => {    console.log("then1");    Promise.resolve()       .then(() => {        console.log("then1-1");        return Promise.resolve();       })       .then(() => {        console.log("then1-2");       });   })   .then(() => {    console.log("then2");   })   .then(() => {    console.log("then3");   })   .then(() => {    console.log("then4");   });復(fù)制代碼

      當(dāng)我們 return Promise.resolve() 時(shí),你猜猜 then1-2 會(huì)何時(shí)打印了?

      答案是最后一個(gè)才被打印出來。

      為什么在 then 中分別 return 不同的東西,微任務(wù)的執(zhí)行順序竟有如此大的變化?以下是筆者的解析。

      PS:then 返回一個(gè)新的 Promise,并且會(huì)用這個(gè) Promise 去 resolve 返回值,這個(gè)概念需要大家先了解一下。

      根據(jù) Promise A+ 規(guī)范

      根據(jù)規(guī)范 2.3.2,如果 resolve 了一個(gè) Promise,需要為其加上一個(gè) thenresolve。

      if (x instanceof MyPromise) {  if (x.currentState === PENDING) {   } else {     x.then(resolve, reject);   }  return; }復(fù)制代碼

      上述代碼節(jié)選自手寫 Promise 實(shí)現(xiàn)。

      那么根據(jù) A+ 規(guī)范來說,如果我們在 then 中返回了 Promise.resolve 的話會(huì)多入隊(duì)一次微任務(wù),但是這個(gè)結(jié)論還是與實(shí)際不符的,因此我們還需要尋找其他權(quán)威的文檔。

      根據(jù) ECMA – 262 規(guī)范

      根據(jù)規(guī)范 25.6.1.3.2,當(dāng) Promise resolve 了一個(gè) Promise 時(shí),會(huì)產(chǎn)生一個(gè)NewPromiseResolveThenableJob,這是屬于 Promise Jobs 中的一種,也就是微任務(wù)。

      This Job uses the supplied thenable and its then method to resolve the given promise. This process must take place as a Job to ensure that the evaluation of the then method occurs after evaluation of any surrounding code has completed.

      并且該 Jobs 還會(huì)調(diào)用一次 then 函數(shù)來 resolve Promise,這也就又生成了一次微任務(wù)。

      這就是為什么會(huì)觸發(fā)兩次微任務(wù)的來源。

      最后

      文章到這里就完結(jié)了,大家有什么疑問都可以在評論區(qū)提出。

      想了解

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號