nextTick源碼解析

nextTick

咱們先把這部分源碼復(fù)制出來

var isUsingMicroTask = false;//nextTick 最終是否以微任務(wù)執(zhí)行,在下面如果瀏覽器支持promise和MutationObserver的話,這個就會改變成true
var callbacks = [];//用來存放nextTick傳進(jìn)來的函數(shù)
var pending = false;
function nextTick(cb, ctx) {
      var _resolve;
      //callbacks在這里是存放傳進(jìn)來的cb
      callbacks.push(function () {
          if (cb) {
            // 同時會進(jìn)行異常捕獲
              try {
                  cb.call(ctx);
              }
              catch (e) {
                  handleError(e, ctx, 'nextTick');
              }
          }
          else if (_resolve) {
              _resolve(ctx);
          }
      });
      if (!pending) {
          pending = true;
          timerFunc();//主要看這里
      }
      // $flow-disable-line
      if (!cb && typeof Promise !== 'undefined') {
          return new Promise(function (resolve) {
              _resolve = resolve;
          });
      }
  }

timerFunc

這里主要使用了Promise.then > MutationObserver > setImmediate > setTimeOut;這四種來實(shí)現(xiàn)異步,然后優(yōu)先級就是這樣

這里主要是在頁面剛引入vue.js的時候,進(jìn)行判斷,看看當(dāng)前環(huán)境是不是支持,咱們可以在這里加上console.log,然后再瀏覽器里面看看

var timerFunc;
// 這里優(yōu)先使用Promise,因?yàn)閜romise的then是微任務(wù),執(zhí)行速度比較快
if (typeof Promise !== 'undefined' && isNative(Promise)) {

console.log('這里使用了Promise')

    var p_1 = Promise.resolve();
    timerFunc = function () {
        p_1.then(flushCallbacks);
        if (isIOS)
            setTimeout(noop);
    };
    isUsingMicroTask = true;
}
else if (!isIE &&
    typeof MutationObserver !== 'undefined' &&
    (isNative(MutationObserver) ||
        MutationObserver.toString() === '[object MutationObserverConstructor]')) {

console.log('這里使用了MutationObserver')

    var counter_1 = 1;
    var observer = new MutationObserver(flushCallbacks);
    var textNode_1 = document.createTextNode(String(counter_1));
    observer.observe(textNode_1, {
        characterData: true
    });
    timerFunc = function () {
        counter_1 = (counter_1 + 1) % 2;
        textNode_1.data = String(counter_1);
    };
    isUsingMicroTask = true;
}
else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {

    console.log('這里使用了setImmediate')

    timerFunc = function () {
        setImmediate(flushCallbacks);
    };
}
else {
    // 這里最后使用setTimeout,
    console.log('這里使用了setTimeout')
    timerFunc = function () {
        setTimeout(flushCallbacks, 0);
    };
}

查看打印的結(jié)果,看到當(dāng)前瀏覽器是支持promise

image.png

flushCallbacks

  function flushCallbacks() {
      pending = false;
// 這里復(fù)制了一份出來,同時清空callbacks
      var copies = callbacks.slice(0);
      callbacks.length = 0;
// 這里遍歷copies里面的函數(shù),然后按順序執(zhí)行
      for (var i = 0; i < copies.length; i++) {
          copies[i]();
      }
  }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容