事件循环与Vue的异步更新(代码注释)

307 阅读1分钟

queueWatcher

queueWatcher方法在每次派发更新的时候都会被调用,传入的是watcher实例。在vue中视图更新是异步的,并且内部维护了一个更新队列queue,一个去重后的watcher集合,两个状态:flushing(队列是否更新中)和waiting(是否开启排队)

这里要注意的是在开启flushing后,新加入watcher的插队及nextTick

flushSchedulerQueue

这里的关键点是queue的排序原因。

Tick

JS是单线程语言,如果所有的函数都是同步执行的,那么必然会导致线程的阻塞,因此有了event loop的方法来解决阻塞的问题。

在红宝书中能见到有提到tick的概念,每一轮事件循环完成之后,被称为一个tick。那么nextTick就是下一个event loop的意思了。也就是异步执行。

下图为事件循环的示意图

Event loop

宏任务:

I/O(文件,网络等)

setTimeout

setInterval

setImmediate

requestAnimationFrame

脚本文件也可以看成一个红任务。

微任务

process.nextTick

promise

MutationObserver

Vue中的nextTick

nextTick核心为 timerFunc函数

timerFunc

v2.6.11版本的异步更新策略

flushCallbacks

细节是拷贝callbacks,然后重置pending的状态,

callbacks是全局唯一的,不像watcher更新的时候queuewacher队列还可以插队。

之前的插队行为应该是为了提升性能,讲更新任务做成异步的,然后再每次更新过程中最大可能地收集更新行为。

而这里的nextTick没有用插队的方式,如果用了那就不能将任务切片了。和同步也没什么差别。