nextTick源码解析

nextTick

咱们先把这部分源码复制出来

var isUsingMicroTask = false;//nextTick 最终是否以微任务执行,在下面如果浏览器支持promise和MutationObserver的话,这个就会改变成true
var callbacks = [];//用来存放nextTick传进来的函数
var pending = false;
function nextTick(cb, ctx) {
      var _resolve;
      //callbacks在这里是存放传进来的cb
      callbacks.push(function () {
          if (cb) {
            // 同时会进行异常捕获
              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;这四种来实现异步,然后优先级就是这样

这里主要是在页面刚引入vue.js的时候,进行判断,看看当前环境是不是支持,咱们可以在这里加上console.log,然后再浏览器里面看看

var timerFunc;
// 这里优先使用Promise,因为promise的then是微任务,执行速度比较快
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);
    };
}

查看打印的结果,看到当前浏览器是支持promise

image.png

flushCallbacks

  function flushCallbacks() {
      pending = false;
// 这里复制了一份出来,同时清空callbacks
      var copies = callbacks.slice(0);
      callbacks.length = 0;
// 这里遍历copies里面的函数,然后按顺序执行
      for (var i = 0; i < copies.length; i++) {
          copies[i]();
      }
  }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容