这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战
一、事件循环机制
宏任务
是很大,且很独立的任务。浏览器完成一个宏任务,在下一个宏任务执行开始前,会对页面进行重新渲染。主要包括创建文档对象、HTML的解析、执行主线js代码、运行脚本以及各种事件例如页面加载,用户的输入、ajax ,定时器setTimeout等
微任务
是当前宏任务执行结束之后(批量)立即执行的任务。如果有微任务,浏览器会清空微任务后再进行重新渲染页面。例如Promise.then的回调函数,dom变化等。
下面可以猜下宏任务和微任务的执行顺序:
console.log('1');
setTimeout(function () {
console.log('2');
}, 0);
Promise.resolve()
.then(function () {
console.log('3');
})
.then(function () {
console.log('4');
});
console.log('5');
解析:
上面代码中两个console.log是同步代码肯定先执行的,所以答案是1,5
然后就看setTimeout和promise哪个先执行了
- 因为setTimeout是宏任务,所以是最后执行的,就算延时的时间是0也是最后执行
- 因为Promise.resolve是微任务,先后两次放入3,4所以按顺序执行。
执行顺序的答案是:1,5,3,4,2
结论:先执行同步代码,然后执行微任务,然后执行宏任务,宏任务执行后会立刻执行微任务,然后浏览器渲染
可以点击:体验一下宏任务和微任务执行的顺序
事件循环机制Event Loop
因为浏览器在执行的过程中需要处理js、脚本的执行、事件的解析、渲染等,有的是同步的有的是异步的,很复杂不好协调,所以需要事件循环机制。
也就是浏览器为了协调事件处理、脚本执行、网络请求和渲染等任务而制定的工作机制
二、vue批量异步更新策略
vue中使用nextTick实现异步更新也就是flushSchedulerQueue(冲刷任务队列)
异步
vue源码中update()方法(地址:core\observer\watcher.js ),dep.notify()之后watcher执行更新,执行入队操作。
只要监听到数据有变化,vue就会开启一个队列,并缓存在同一事件循环中发生的所有数据更新。
批量
如果有一个watcher被多次触发,只会被推入到队列中一次,并且去重(每个watcher都有一个唯一的id)避免不必要的计算工作和DOM操作。然后在下一个事件循环机制中,vue刷新队列执行实际工作。
异步策略
vue在内部对异步队列用Promise.then、MutationObserver或setImmediate这些微任务批量执行,如果这些环境不支持的话就会用宏任务setTimeout代替。
nextTick(flushSchedulerQueue);是用异步的方式将flushSchedulerQueue(冲刷任务队列)放入微任务队列。然后启动异步的执行timerFunc()就是上面说的promise.then和MutationObserver判断环境是否支持最后通知更新;
最后异步更新系列写的比较简单,大家最好下载源码加断点执行一次看看执行顺序影响会比较深,最后感谢阅读~