• <center id="sm46c"></center>
  • <dfn id="sm46c"></dfn>
  • <strike id="sm46c"></strike>
  • <cite id="sm46c"><source id="sm46c"></source></cite>
    • <strike id="sm46c"><source id="sm46c"></source></strike>
      <option id="sm46c"></option>
      国产精品天天看天天狠,女高中生强奷系列在线播放,久久无码免费的a毛片大全,国产日韩综合av在线,亚洲国产中文综合专区在,特殊重囗味sm在线观看无码,中文字幕一区二区三区四区在线,无码任你躁久久久久久老妇蜜桃

      Promise 你真的用明白了么?

      2020-9-2    seo達(dá)人

      前置知識

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

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

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

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

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

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

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

      了解完以上知識后,正片開始。

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

      初級

      Promise.resolve()
        .then(() => { console.log("then1"); Promise.resolve().then(() => { console.log("then1-1");
          });
        })
        .then(() => { console.log("then2");
        });

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

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

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

      中級

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

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

      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");
      }); 

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

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

      接下來我們換個寫法:

      let p = Promise.resolve().then(() => { console.log("then1"); Promise.resolve().then(() => { console.log("then1-1");
        });
      }).then(() => { console.log("then2");
      });
      
      p.then(() => { console.log("then3");
      });

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

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

      高級

      以下大家可以猜猜 then1-2 會在何時打印出來?

      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");
        });

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

      • 第一次 resolve 后第一個 then 的回調(diào)進(jìn)入微任務(wù)隊列并執(zhí)行,打印 then1
      • 第二次 resolve 后內(nèi)部第一個 then 的回調(diào)進(jìn)入微任務(wù)隊列,此時外部第一個 then 的回調(diào)全部執(zhí)行完畢,需要將外部的第二個 then 回調(diào)也插入微任務(wù)隊列。
      • 執(zhí)行微任務(wù),打印 then1-1 和 then2,然后分別再將之后 then 中的回調(diào)插入微任務(wù)隊列
      • 執(zhí)行微任務(wù),打印 then1-2 和 then3 ,之后的內(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");
        });

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

      答案是最后一個才被打印出來。

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

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

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

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

      if (x instanceof MyPromise) { if (x.currentState === PENDING) {
        } else {
          x.then(resolve, reject);
        } return;
      }

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

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

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

      根據(jù)規(guī)范 25.6.1.3.2,當(dāng) Promise resolve 了一個 Promise 時,會產(chǎn)生一個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 還會調(diào)用一次 then 函數(shù)來 resolve Promise,這也就又生成了一次微任務(wù)。

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

      藍(lán)藍(lán)設(shè)計www.li-bodun.cn )是一家專注而深入的界面設(shè)計公司,為期望卓越的國內(nèi)外企業(yè)提供卓越的UI界面設(shè)計、BS界面設(shè)計 、 cs界面設(shè)計 、 ipad界面設(shè)計 、 包裝設(shè)計 、 圖標(biāo)定制 、 用戶體驗 、交互設(shè)計、 網(wǎng)站建設(shè) 平面設(shè)計服務(wù)

      日歷

      鏈接

      個人資料

      存檔

      主站蜘蛛池模板: 性欧美久久| 东京热久久综合久久88| 亚洲一区二区三区黄色片| 巨胸美乳无码人妻视频| 日韩精品一区二区在线视 | 久久青草视频| 国产欧亚州美日韩综合区| 亚洲欧美日本国产综合一区二区| 国产成人精品三上悠亚久久| 色一情一乱一伦麻豆| 影音先锋无码a∨男人资源站| 亚洲视频在线观看免费视频| 特级毛片在线大全免费播放| 免费一区二区三区视频狠狠| 五月婷婷激情六月| 网久久综合| 久久精品国产99久久六动漫| 亚洲av噜噜一区二区| 国产一区二区三区免费观看在线| 无码人妻斩一区二区三区| 国产农村妇女精品一二区| 国产在线欧美日韩一区二区| 久久香综合精品久久伊人| 国产无内肉丝精品视频| 亚洲欧洲日产国码无码久久99| 亚洲一区无码精品色| 国产精品ⅴ无码大片在线看| 国产成人亚洲综合色婷婷秒播| 精品国产免费观看一区| 波多野结衣av在线免费| 九九精品热| 国产97人人超碰CAO蜜芽PROM| 亚洲国产欧美一区二区好看电影| 国产精品一区二区亚瑟不卡| 久久国产自偷自偷免费一区调| 无码av中文一区二区三区| 日韩 欧美 国产 一区三| 国产 | 久你欧洲野花视频欧洲1| 岛国岛国免费v片在线观看| 日韩精品一二三黄色一级| 国产一区二区在线影院|