第二十七篇 如何理解EventLoop的宏任务和微任务
宏任务(MacroTask)引入
在 JS 中,大部分的任务都是在主线程上执行,常见的任务有:
- 渲染事件
- 用户交互事件
- js 脚本执行
- 网络请求、文件读写完成事件等等。
为了让这些事件有条不紊地进行,JS 引擎需要对之执行的顺序做一定的安排,V8 其实采用的是一种队列的方式来存储这些任务, 即先进来的先执行。模拟如下:
bool keep_running = true;
void MainTherad(){
for(;;){
//执行队列中的任务
Task task = task_queue.takeTask();
ProcessTask(task);
//执行延迟队列中的任务
ProcessDelayTask()
if(!keep_running) //如果设置了退出标志,那么直接退出线程循环
break;
}
}
这里用到了一个 for 循环,将队列中的任务一一取出,然后执行,这个很好理解。但是其中包含了两种任务队列,除了上述提到的任务队列,还有一个延迟队列,它专门处理诸如 setTimeout/setInterval 这样的定时器回调任务。
上述提到的,普通任务队列和延迟队列中的任务,都属于宏任务。
微任务(MicroTask)引入
对于每个宏任务而言,其内部都有一个微任务队列。那为什么要引入微任务?微任务在什么时候执行呢?
其实引入微任务的初衷是为了解决异步回调的问题。想一想,对于异步回调的处理,有多少种方式?总结起来有两点:
- 将异步回调进行宏任务队列的入队操作。
- 将异步回调放到当前宏任务的末尾。
如果采用第一种方式,那么执行回调的时机应该是在前面所有的宏任务完成之后,倘若现在的任务队列非常长,那么回调迟迟得不到执行,造成应用卡顿。
为了规避这样的问题,V8 引入了第二种方式,这就是微任务的解决方式。在每一个宏任务中定义一个微任务队列,当该宏任务执行完成,会检查其中的微任务队列,如果为空则直接执行下一个宏任务,如果不为空,则依次执行微任务,执行完成才去执行下一个宏任务。
常见的微任务有 MutationObserver、Promise.then(或.reject)以及以 Promise 为基础开发的其他技术(比如 fetch API),还包括 V8 的垃圾回收过程。
Ok,这便是宏任务和微任务的概念,接下来正式介绍 JS 非常重要的运行机制——EventLoop。
更多相关文章推荐:
以上关于第二十七篇 如何理解EventLoop的宏任务和微任务的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » 第二十七篇 如何理解EventLoop的宏任务和微任务
微信
支付宝