js运行机制

JS 执⾏是单线程的,它是基于事件循环的。事件循环⼤致分为以下⼏个步骤:

  • 所有同步任务都在主线程上执⾏,形成⼀个执⾏栈。

  • 主线程之外,还存在⼀个"任务队列"。只要异步任务有了运⾏结果,就在"任务队列"之中放置事件回调。

  • ⼀旦"执⾏栈"中的所有同步任务执⾏完毕,系统就会读取"任务队列",有事件就放入主线程中,开始执⾏。

  • 不断重复上面三步

主线程的执⾏过程就是⼀个 tick,⽽所有的异步结果都是通过 “任务队列” 来调度被调度。 任务队列中存放的是⼀个个的任务。 规范中规定任务分为两⼤类,分别是 macro task(宏任务)和 micro task(微任务),并且每个宏任务结束后,都要去轮询微任务也就是执行微任务。

在浏览器环境中,常⻅的宏任务有 setTimeout、MessageChannel、postMessage、setImmediate;常⻅的微任务有 MutationObsever 和 Promise.then。

nextTick
  1. 使用涉及地方
  • global-api/indes.js Vue.nextTick = nextTick
  • instance/render.js  Vue.prototype.$nextTick = function (fn: Function) {return nextTick(fn, this)}
  • observer/scheduler.js nextTick(flushSchedulerQueue)
  1. 两种写法
  • nextTick with cb 和 nextTick with promise 两种写法
  1. nextTick
timerFunc()

Vue 在内部对异步队列尝试使用原生的 Promise.then 、 MutationObserver 和 setImmediate ,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。

flushCallbacks

总结

1.nextTick两种方式调用一种直接cb一种通过promise后再回调。

2.对于直接cb,首先往callbacks数组中丢入回调函数,函数内容通过try,catch执行cb确保cb函数内容无报错。初始pending为false首先设置为true并执行timeFunc。timeFunc根据浏览器支持方式做不通的调用,最终执行flushCallbacks。flushCallbacks首先把pending设为false,然后复制一份callbacks数组最后遍历执行回调函数。

3.对于promise后再回调,首先往callbacks数组中丢入_resolve,_resolve是new Promise的resolve的赋值。初始pending为false首先设置为true并执行timeFunc。timeFunc根据浏览器支持方式做不通的调用,最终执行flushCallbacks。flushCallbacks首先把pending设为false,然后复制一份callbacks数组最终返回reslove然后执行.then的回调。

4.通过这⼀节对 nextTick 的分析,并结合上⼀节的 set 分析,我们了解到数据的变化到 DOM 的重新渲染是⼀个异步过程,发⽣在下⼀个 tick。这就是我们平时在开发的过程中,⽐如从服务端接⼝去获取数据的时候,数据做了修改,如果我们的某些⽅法去依赖了数据修改后的 DOM 变化,我们就必须在nextTick 后执⾏。