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就是利用微任务的特点来进行统一管理的

 

posted @ 2021-11-08 17:02  C+V-Engineer  阅读(412)  评论(0编辑  收藏  举报