Vue.prototype.$nextTick = function (fn) { return nextTick(fn, this) };
nextTick方法中,把要执行的方法(cb)放到callbacks这个数组中,然后进入timerFunc,源码1929行(左右)可以看到,timerFunc的作用是把flushCallbacks这个函数放到promise的微任务队列。而flushCallbacks中,把之前callbacks中的元素取出来执行。
pending是个flag,保证每次只会将一个flushCallbacks放到微任务队列,毕竟执行的还是callbacks中的方法,flushCallbacks方法只是一个开关,在方法的第一句会把pending赋值为false(不能放在最后一句,那样的话,后添加的cb中,
如果是当前宏任务添加的,会执行,而微任务执行过程中,后添加的cb,将不会被执行,具体看源码)。
延伸一点,Watcher的update方法中queueWatcher(this),把自己放到queue这个队列中,调用nextTick(flushSchedulerQueue),根据上面的分析,是把flushSchedulerQueue放到callbacks中,再在微任务队列中执行。
flushSchedulerQueue这个方法中,会解决重复watcher的问题,然后调用watcher.run()。其中的flushing和waiting也是两个flag开关,和上面说的pending一致。
设想一下,如果一个页面上显示的变量(比如叫name)的set方法A,和一个$nextTick(它的cb的逻辑是获取这个页面上name的值打印)--B,A和B的执行的先后顺序也是很有意思的事情,A在B之前执行,b获取到的就是改变后的值,反之就是改变前的值。
这是因为callbacks中,两个cb放的顺序不同,导致微任务中,执行的先后顺序不同。