【16】winter重學前端 - JavaScript執行(一):Promise裏的代碼爲何比setTimeout先執行?

js實現異步的幾種形式

  • 回調函數
  • 事件監聽 - 事件驅動模式
  • 發佈/訂閱 - 觀察者模式
  • Promises對象

js異步歷史

  • 一個 JavaScript 引擎會常駐於內存中,它等待着咱們把JavaScript 代碼或者函數傳遞給它執行
  • 在 ES3 和更早的版本中,JavaScript 自己尚未異步執行代碼的能力,引擎就把代碼直接順次執行了,這個任務也就是宿主發起的任務。
  • 在 ES5 以後,JavaScript 引入了 Promise,這樣,不須要瀏覽器的安排,JavaScript 引擎自己也能夠發起任務了。

宏觀和微觀任務

  • 宏觀任務:宿主發起的任務,每次的一段js代碼執行過程,其實都是一個宏觀任務(可大體理解爲:宏觀任務的隊列就至關於事件循環)- 宿主級別
  • 微觀任務:JavaScript 引擎發起的任務 - JS 引擎級別
  • 關係:每一個宏觀任務中維護一個微觀任務隊列 - 宏觀任務中,JavaScript 的 Promise 還會產生異步代碼,JavaScript 必須保證這些異步代碼在一個宏觀任務中完成
  • 例子瀏覽器

    • Promise 永遠在隊列尾部添加微觀任務
    • setTimeout 等宿主 API,則會添加宏觀任務
  • 執行順序:異步

    • 微觀任務:在所屬的宏觀任務隊列全部同步任務執行完成以後執行
    • 宏觀任務:宏任務的觸發規則和調用次序
  • eg:執行一個耗時 1 秒的 Promise。
    即便耗時一秒的 c1 執行完畢,再 enque 的 c2,仍然先於 d 執行了,這很好地解釋了微任務優先的原理。函數

    setTimeout(()=>console.log("d"), 0)
      var r1 = new Promise(function(resolve, reject){
          resolve()
      });
      r.then(() => { 
          var begin = Date.now();
          // 強制了 1 秒的執行耗時,這樣,咱們能夠確保任務 c2 是在setTimeout d後加入任務隊列
          while(Date.now() - begin < 1000);
          console.log("c1") 
          new Promise(function(resolve, reject){
              resolve()
          }).then(() => console.log("c2"))
      });

事件循環

    • 定義:JavaScript 引擎等待宿主環境分配宏觀任務,在操做系統中,一般等待的行爲都是一個事件循環 - 就是反覆「等待 - 執行」
    • 功能:判斷循環是否結束、宏觀任務隊列等邏輯
    • 如何分析異步執行的順序:操作系統

      • 首先咱們分析有多少個宏任務;
      • 在每一個宏任務中,分析有多少個微任務;
      • 根據調用次序,肯定宏任務中的微任務執行次序;
      • 根據宏任務的觸發規則和調用次序,肯定宏任務的執行次序;
      • 肯定整個順序。
    • eg:
      setTimeout 把整個代碼分割成了 2 個宏觀任務,這裏不管是 5 秒仍是 0 秒,都是同樣的。
      第一個宏觀任務中,包含了前後同步執行的 console.log(「a」); 和 console.log("b")
      setTimeout 後,第二個宏觀任務執行調用了resolve,而後 then 中的代碼異步獲得執行,因此調用了 console.log(「c」),最終輸出的順序纔是a,b,ccode

      function sleep(duration) {
              return new Promise(function(resolve, reject) {
                  console.log("b");
                  setTimeout(resolve,duration);
              })
          }
          console.log("a");
          sleep(5000).then(()=>console.log("c"));
    相關文章
    相關標籤/搜索