5分钟看完文章,即可解决大部分执行顺序的题目,那些题都是跟事件循环机制有关。(个人水平有限咯,如有错误欢迎指出)
之前写过一篇,宏任务与微任务的执行顺序,但是这不是根本,今天我觉得很有必要讲一下event loop。
进入正题,地球人都知道js是单线程。那么它可能存在执行任务时候任务阻塞,Event Loop的出现,就是完美的解决了这个问题。
1、首先我们知道js代码执行分为同步任务
和异步任务
同步: script代码块(如console.log)
异步又分为:
宏任务:setTimeout
、I/O
微任务:promise.then()
、async的await
、new MutationObserver()
我们可以看到它的异步又分为宏任务与微任务(面试中经常提到的执行顺序)。
2、调用栈和任务队列
栈
和队列
的执行顺序
请看下面图例,js执行任务时候,有个调用栈用来执行代码,两个任务队列(宏任务、微任务),A、B是两个函数。
很容易理解,栈是先进后出,而队列则不同,是先进先出。
到这里对事件循环的基础了解有了60%。接下来就了解知道它是大概怎么执行循环的。
3、事件循环 Event Loop执行顺序(重点)
上面列举的代码模块按照一定的机制循环执行,就是Event Loop,也叫事件循环。
要了解它的执行顺序有两点:
1、js是在调用栈里面执行,执行时代码分为同步任务
和异步任务
。同步的先执行,执行完了再执行异步任务代码。为什么?可以理解为不清楚异步是什么时候执行完成的,所以同步代码先执行。
2、接第一点,同步代码全部执行完后
才开始执行异步,异步里微任务比宏任务先执行(理解为微任务执行比较快,为了方便你记忆),直到微任务队列没了,才去执行宏任务。
假设有如下代码块,我们按照上面的
setTimeout(() => {
console.log(1);
}, 0)
console.log(2)
new Promise((resolve) => {
resolve(3)
}).then(res => console.log(res))
function foo() {
console.log(4);
}
foo()
new Promise((resolve) => {
resolve(6)
}).then(res => console.log(res))
这个代码块,执行时,第一轮结束时候,会是如下结果(所有代码都会进入执行栈里执行时候弹出,这个过程不画了):
同步任务全部执行完毕,直接在控制台分别打印 2 ---- 4 ,(其实执行期间)异步任务会分别被分配到
宏任务队列
和微任务队列
,此时开始执行下一轮的任务事件,第二轮,我们来看下,它的图解:微任务console.log(3)
进入执行栈,然后弹出,所以在控制台先输出3,然后再检查是否有微任务,console.log(6)
再进入执行栈,然后弹出,控制台输出6。
接着第三轮,就是剩下宏任务了,运行宏任务队列代码块console.log(1)
,控制台输出1。
所以最终结果就是:2---4---3---6---1
看到这里了解了吗?代码按规律循环执行这就是 事件循环Event Loop,有没有很简单。
但是但是但是,如果只会这点的话不行啦,遇到稍微复杂一点的循环就有点蒙,而且,有坑点
。请看我这篇文章:
js事件循环简单理解,微任务与宏任务运行顺序(二)
看完你会回来感谢我的。