谈谈对vue的nexttick和eventloop的理解

1. eventloop

在这里插入图片描述此图为eventloop的直观图,附上个人理解:
将代码划分成立即执行代码,宏任务代码,微任务代码,后两者分别放入宏队列和微队列当中,立即执行代码执行后执行所有微任务,这算第一轮结束,然后再执行第二个宏任务,如此循环.

例题:
在这里插入图片描述
执行结果为:
1 7 6 8 2 4 3 5 9 11 10 12 分为四轮执行

注意:执行顺序
promise>nexttick>then>settimeout
因为
Promise是一个micro task 主线程是一个task micro task queue会在task后面执行
promise.then是一个micro task

setTimeout返回的函数是一个新的task macro task queue
所以Promise以及promise.then会先于新task执行
至于为什么nexttick会比promise.then先执行:
在Node中,_tickCallback在每一次执行完TaskQueue中的一个任务后被调用,而这个_tickCallback中实质上干了两件事:
1.nextTickQueue中所有任务执行掉(长度最大1e4,Node版本v6.9.1)
2.第一步执行完后执行_runMicrotasks函数,执行microtask中的部分(promise.then注册的回调)所以很明显process.nextTick > promise.then”

2.为了能在DOM更新之后操作新元素,必须要对操作行为进行延时(队列控制)

每一次事件循环都包含一个microtask队列,在循环结束后会依次执行队列中的microtask并移除,然后再开始下一次事件循环。

在执行microtask的过程中后加入microtask队列的微任务,也会在下一次事件循环之前被执行。也就是说,macrotask总要等到microtask都执行完后才能执行,microtask有着更高的优先级。

microtask的这一特性,简直是做队列控制的最佳选择啊!vue进行DOM更新内部也是调用nextTick来做异步队列控制。而当我们自己调用nextTick的时候,它就在更新DOM的那个microtask后追加了我们自己的回调函数,从而确保我们的代码在DOM更新后执行,同时也避免了setTimeout可能存在的多次执行问题。

常见的microtask有:Promise、MutationObserver、Object.observe(废弃),以及nodejs中的process.nextTick.

nexttick源码中显示,优先度:promise>MO>settimeout(但会因为兼容问题而降级)

//1. promise.then延迟调用
if (typeof Promise !== 'undefined' && isNative(Promise)) {
  var p = Promise.resolve();
  var logError = function (err) { console.error(err); };
  timerFunc = function () {
    p.then(nextTickHandler).catch(logError);
    if (isIOS) { setTimeout(noop); }
  };
}
//2. MutationObserver 监听变化
else if (typeof MutationObserver !== 'undefined' && (
  isNative(MutationObserver) ||
  MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {

  var counter = 1;
  var observer = new MutationObserver(nextTickHandler);
  var textNode = document.createTextNode(String(counter));
  observer.observe(textNode, {
    characterData: true
  });
  timerFunc = function () {
    counter = (counter + 1) % 2;
    textNode.data = String(counter);
  };
}
//3.setTimeout延迟器
else {
    timerFunc = function () {
      setTimeout(nextTickHandler, 0);
    };
  }

3.总结

nexttick源码前半段是为了延时nexttickdhandle函数,promise,mo,settimeout,nexttickdhandle函数就是执行回调函数nexttick为了解决回调函数在dom渲染之后进行,利用了微任务这个概念(microtask因为其高优先级特性,能确保队列中的微任务在一次事件循环前被执行完毕),即以微任务的形式添加操作任务,这个操作任务会在dom这个微任务执行后完成(因为是后添加的),我们把这个解决方案叫队列控制,然而实现队列控制的最佳选择是promise,所以在nexttick源码体现出来的方式是优先判断是否兼容promsie

参考文章:
全面解析Vue.nextTick实现原理
vue之nextTick全面解析

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值