八分钟时间带你了解事件循环 Eventloop
开门见山
甲丢出两道题目,让乙说一下它们的输出结果。
console.log('甲');
setTimeout(function() {
console.log('乙');
}, 0);
console.log('丙');
setTimeout(function() {
console.log('甲');
},0);
console.log('乙');
for(var i = 0; i < 3; i++) {
console.log('丙');
}
console.log('丁');
乙思索了片刻:这么简单。于是唰唰地就把他心中的答案报出来了。第一题是甲乙丙,第二题是甲乙丙丙丙丁。
有多少人和乙答案一样。很显然,最终还是错了。
正确答案如下:
乙十分不解,于是甲便和乙讲起了事件循环的前世今生......
前言
事件循环相关的题目非常经典的题目。很多人了解了事件循环后,都觉得自己已经掌握了(比如我就是这样的)。但是每当被问到的时候,却又不知道该从哪里开始说起,或者说它到底是什么。这是事实,也是让很多人头疼的一个知识点。正好这次通过前面提到的两道题目来看看这个让我们疑惑的事件循环机制。
何为事件循环机制
我们先来了解一下什么是事件循环机制?或者说为什么会有这个机制?
JavaScript
是一门单线程语言,所以很多时候无法满足在不同的时间去执行不同的任务,因此为了满足这样的需求,便衍生出了事件循环机制。
对于事件循环 Event Loop 简单点理解就是 JavaScript
管理事件执行的一个流程,它会不断地从任务队列中读取任务并执行任务。JavaScript
中任务分成同步任务和异步任务。
其实对于事件循环它分为浏览器事件循环和 node
事件循环。比如如果在面试的时候他会让你说一说浏览器和 node
的事件循环。今天我们这里主要讨论浏览器的事件循环。
同步异步任务VS宏微任务
基本认为所有的任务可以分为同步任务和异步任务。同步任务,顾名思义,就是立即执行的任务;而异步任务,就是异步执行的任务,比如 ajax
网络请求,setTimeout
定时函数等都属于异步任务,异步任务会通过任务队列的机制(先进先出的机制)来进行协调。浏览器的事件循环中分成宏任务和微任务。记住一点,setTimeout
是个宏任务,而 pormise
是个微任务,并且微任务要比宏任务执行的要早。
现在来分析一下如下这段代码:
console.log('start');
setTimeout(function() {
console.log('middle');
}, 0);
Promise.resolve().then(function() {
console.log('a');
}).then(function() {
console.log('b');
});
console.log('end');
最终会是怎么样的打印结果,大家可以研究探讨一下。
异步操作都是放到事件循环队列里面,等待主执行栈来执行的,并没有专门的异步执行线程。这段代码整体而言和上面相比加入了 promise
。这里总共存在三个任务,分别是一个宏任务 setTimeout
,两个微任务 then
。执行微任务,首先执行第一个 then
,然后执行第二个 then
。最后执行宏任务 setTimeout
。因此最终的结果会如下所示,将这题理清楚基本就能明白上面两题的结果了。
打印结果如下:
总结
事件循环是 JavaScript
中非常重要且基础的概念。清楚地了解事件循环的执行顺序和特点,会巩固我们的 JS
基础,也可以让我们对同步异步代码的执行顺序有一个清晰的认识。(比如就不会像前文中提到的乙一样👀)
总之,事件循环还需要深入研究,这里结合了简单的例子将事件循环带大家了解了一下,对事件循环有个初步认识。关于我对事件循环的学习还在继续......
转载自:https://juejin.cn/post/7176628445203005497