Vue3源码分析之微任务队列
参考资料:https://zh.javascript.info/microtask-queue#wei-ren-wu-dui-lie-microtaskqueue
简化版 Vue3 中的 微任务队列实例及说明:
// 任务队列 const queue = [] // 创建一个异步函数 const task = Promise.resolve() function nextTick(fn) { task.then(fn) } // k 这个参数是为了调试 function queueJob(job, k) { // 如果队列中不存在这个 任务,则先存入队列 if(!queue.find(c => c.job === job)) { queue.push({ job, key: k}) // 执行所有的任务 queueFlush() } } function queueFlush() { const taskFn = () => { let job; // 每执行完成一个任务就从队列中移除 while ((job = queue.shift())) { if (job) { // 输出的是第几次加入队列的函数 console.log(job.key) job.job(); } } } // taskFn 这个函数其实并没有被立即执行,而是先存入了 微任务队列(PromiseJobs) // 需要等待当前代码执行完成并且先前排队的处理程序(handler)都完成时才会被执行 // 由于每次都会执行所有任务后都会清空队列 // 所以保证只会执行最后一次放入 queue 队列的所有任务 nextTick(taskFn) } // ---- 测试 ---- let i = 0 function fn1() { console.log(i) } i++ // 输出 -> 11 // 该任务没有被立即执行,而是等待当前代码执行完成之后才被执行,所以 i = (0 + 1 + 10) = 11 queueJob(fn1, 'a') i += 10 queueJob(fn1, 'b') // 不会被加入队列,因为队列中已经存在该任务了
在Vue3中,利用 微任务 队列确保不会因为依赖而导致许多不必要的更新,比如:
const count = ref(0) <template> <div>{{ count }}</div> <tempalte> for(let i = 0; i < 100; i++) { count ++ }
如果没有通过微任务进行管理,那么会更新100次,但是只有当 for 被执行完成之后更新才是有必要的,Vue3就是利用微任务的特点来进行统一管理的