看了一些vue nextTick引发的bug, github.com/DDFE/DDFE-b… github.com/vuejs/vue/i… 实际上,vue在macrotask 和 microtask的问题上反复好久,有时micro 优先,有时 macro 优先,有时可以指定谁优先。
引发问题的原因是因为event冒泡的优先级小于microtask,用macro task 对transitions的执行有影响。
nextTick的代码是维护了一个callbacks队列,dep数据更新之后触发的操作会push到callbacks中,然后把callbacks的callback挨个执行,nextTict分为两种调用方式,带参数cb的和不带cb的。带cb的会把用户的cutom cb放到callbacks队列最后执行,不带cb参数的会返会一个promise,并在callbasks执行完成后resovled。
我实现了一个microtask的nectTick,不考虑schedule函数的细节,只看看它做了什么
const callbacks = []
let pending = false
function flushCallbacks() {
return Promise.resolve().then(() => {
pending = false
const copies = callbacks.slice(0)
callbacks.length = 0
for (let i = 0; i < copies.length; i++) {
console.log('copy i', i, 'copies length', copies.length)
copies[i]()
}
})
}
function nextTick(callback) {
let _resolve
console.log('callbacks length', callbacks.length)
callbacks.push(() => {
if (callback) {
callback.call()
} else if (_resolve) {
_resolve()
}
})
console.log('pending', pending)
if (!pending) {
pending = true
flushCallbacks()
}
if (!callback) {
return new Promise(resolve => {
_resolve = resolve
})
}
}
function test1() {
console.log('test1')
}
function test2() {
console.log('test2')
}
nextTick(test1)
nextTick(test2)
nextTick(test2)
nextTick(test2)
nextTick(test2)
其中有一点没想明白,flushCallbacks 中为什么要复制一遍callbacks,而不是在callbacks执行完成后再清空它。请各位不吝赐教。