十四、Vue源码-异步更新

118 阅读2分钟

一、浏览器异步策略

1、当我们执行 JS 代码的时候其实就是往执行栈(同步) (Call Stack) 中放入函数;

2、遇到异步代码的时候该怎么办?其实当遇到异步的代码时,会被挂起并在需要执行的时候加入到 Task(有多种 Task) 队列中(异步的Task: 有宏任务Task, 和 微任务Task);

3、一旦执行栈为空,Event Loop 就会从 Task 队列中拿出需要执行的代码并放入执行栈中执行,所以本质上来说 JS 中的异步还是同步行为。


一、Event Loop

执行顺序如下所示:

  • 首先执行同步代码,这属于宏任务
  • 当执行完所有同步代码后,执行栈call stack 为空,查询是否有异步代码需要执行
  • 执行所有微任务
  • 当执行完所有微任务后,如有必要会渲染页面(渲染)
  • 然后开始下一轮 Event Loop,执行宏任务中的异步代码,也就是 setTimeout 中的回调函数

二、微任务 (在渲染页面前)

包括 process.nextTick ,异步(promise ,MutationObserver)


三、宏任务(在渲染页面后)

包括 script ,异步( setImmediate, setTimeout  ,setInterval)  ,I/O ,UI rendering 。


四、误区****

这里很多人会有个误区,认为微任务快于宏任务,其实是错误的。

因为宏任务中包括了 script ,浏览器会先执行一个宏任务, 接下来有异步代码的话才会先执行微任务。


五、正确顺序:

开始1个宏任务->再是微任务->再是浏览器渲染一次页面->再开始另一个宏任务,再是微任务,再是渲染。

如果微任务  microtask queue 没有清空 ,下一个宏任务不会开始

二、Vue源码-异步更新

Vue高效的秘诀是一套批量、异步的更新策略。

1、策略

异步:只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。

批量:如果同一个 watcher 被多次触发,只会被推入到队列中一次。去重对于避免不必要的计算 和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列执行实际工作。

异步策略:Vue 在内部对异步队列尝试使用原生的 Promise.then 、 MutationObserver 或

setImmediate ,如果执行环境都不支持,则会采用 setTimeout 代替。

2、异步更新思维导图

3、指导绘制