事件循环
- 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
- 主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
- 一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
- 主线程不断重复上面的第三步。
除了广义的同步任务和异步任务,我们对任务有更精细的定义:
- macro-task(宏任务):包括整体代码script,setTimeout,setInterval,setImmediate,I/O,UI rendering
- micro-task(微任务):Promise,process.nextTick(nodejs),MutationObserver
不同类型的任务会进入对应的Event Queue,比如setTimeout和setInterval会进入相同的Event Queue
宏任务 Event Queue 微任务 Event Queue
setTimeout nextTick then
事件循环的顺序,决定js代码的执行顺序。进入整体代码(宏任务)后,开始第一次循环。接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。
setTimeout(function() {
console.log('setTimeout');
})
new Promise(function(resolve) {
console.log('promise');
}).then(function() {
console.log('then');
})
console.log('console');
-
这段代码作为宏任务,进入主线程。
-
先遇到
setTimeout,那么将其回调函数注册后分发到宏任务Event Queue。(注册过程与上同,下文不再描述) -
接下来遇到了
Promise,new Promise立即执行,then函数分发到微任务Event Queue。 -
遇到
console.log(),立即执行。 -
好啦,整体代码script作为第一个宏任务执行结束,看看有哪些微任务?我们发现了
then在微任务Event Queue里面,执行。 -
ok,第一轮事件循环结束了,我们开始第二轮循环,当然要从宏任务Event Queue开始。我们发现了宏任务Event Queue中
setTimeout对应的回调函数,立即执行。 -
结束。
javascript是一门单线程语言
Event Loop是javascript的执行机制
参考文章来源:juejin.cn/post/684490…