nextTick 是微任务还是宏任务?70%的人都回答错了吧~

3420次阅读  |  发布于2年以前

前言

大家好, 用最通俗易懂的话讲最难的知识点是我的座右铭,基础是进阶的前提是我的初心。

nextTick有啥用?

我们常常有这样的一个场景,改变了一个值之后,我们需要获取到最新的DOM信息,去做一些操作,比如

我们可以看到,第一次输出DOM信息的时候并不是最新的,但是在nextTick中输出的DOM信息是最新的。

那我们可以看出nextTick的作用是:当响应式数据更改后,能在回调中拿到最新的DOM信息。

nextTick是怎么做到的?

在这之前我们先想一个问题,比如你更新了10次数据,难道就会更新DOM 10次吗?

for(let i = 0; i < 10; i++) {
  this.num = i // 10次
}

答案是不会的,因为更新太频繁太影响性能了,那么Vue是怎么做这里的优化的呢?

其实就一个思想:将多次更新的事件合在一个数组中,然后一次性去进行更新,这样大大减少了更新频繁的问题。

那是怎么实现的呢?其实是利用异步更新,我举个简单的例子哈:

注意:例子比较简单,实际源码不是这么简单,只是为了好理解~

const queue = []
for(let i = 0; i < 10; i++) {
  this.num = i
  // 相当于改变num所触发的更新事件
  queue.push(() => console.log(i))
}

// 微任务,异步执行
const nextTick = (cb) => {
  Promise.resolve().then(() => {
    queue.forEach(event => event())
    // 更新完后的回调
    cb()
  })
}

// 宏任务,也是异步执行
const nextTick = (cb) => {
  setTimeout(() => {
    queue.forEach(event => event())
    // 更新完后的回调
    cb()
  })
}

nextTick是微任务吗?

相信很多面试官问你nextTick是什么类型的任务?很多人都会回答微任务,因为大部分觉得nextTick === then

但其实这是不然的,正确的说法应该是nextTick优先是微任务,咱们可以来看看nextTick的部分源码,就知道了:

其实nexTick只是优先选择微任务而已,如果当前运行环境不支持微任务的话,还是会选择宏任务的~~

为啥优先微任务呢?

我的理解是:首先,代码的正常运行是一个宏任务,如果nextTick是一个宏任务的话,那么刚刚的queue.forEach(event => event())就会在下一个宏任务中去执行,但是你并不知道在nextTick之前还产生了多少宏任务,可能产生了10个,那整个执行的流程就是这样:

所以nextTick如果是宏任务,那么不定因素很多,可能会隔很久才去执行

那如果是微任务呢?我们知道,微任务会在本次宏任务末尾去执行,所以即使在nextTick之前已经产生了10个宏任务,也不会影响nextTick的执行时机

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8