参考:这篇文章的总结
因为JS有同步任务和异步任务,就造成了JS多线程的假象,但是JS是一门单线程语言!
JS的执行机制是根据事件循环的顺序。
宏任务和微任务
因为JS有同步任务和异步任务,为了了解执行机制,将任务细分为宏任务和微任务。
-
macro-task(宏任务):包括整体代码script,setTimeout,setInterval
-
micro-task(微任务):Promise,process.nextTick
宏任务和微任务还包括其他的,这里不赘述
事件循环
事件循环的顺序就是:
- 进入整体代码(宏任务)后,开始第一次循环。
- 接着执行所有的微任务。
- 然后再次从宏任务开始,找到其中一个任务队列执行完毕
- 再执行所有的微任务。
注意
第一次进入整体代码时,就将立即执行的执行了,有宏任务就放入宏任务队列,有微任务放入微任务队列。
此时有没执行的宏任务和微任务,但是因为刚刚执行了宏任务(整体代码),所以这次循环要执行微任务,并且每次执行微任务都要执行所有的微任务。
执行完这次所有的微任务,就循环去执行宏任务。记住除了第一次,以后再执行宏任务都只执行一个宏任务。
如果又有微任务,就再去循环执行所有的微任务……再去循环执行一个宏任务……执行所有的微任务……执行一个宏任务……
例子
举一个小例子
setTimeout(function() {
console.log('setTimeout');
});
new Promise(function(resolve) {
console.log('promise');
resolve();
}).then(function() {
console.log('then');
});
console.log('console');
复制代码
promise
console
then
setTimeout
复制代码
解析
-
第一次循环整体代码(宏任务),
new Promise
立即执行,输出promise
。console.log('console')
也立即执行,输出console
这次循环后宏任务队列有:
setTimeout
,微任务队列有:promise的
.then
-
第二次循环要执行所有的微任务了,即promise的
.then
,输出then
-
第三次循环要执行一个宏任务了,即
setTimeout
,输出setTimeout
总结
只要记住
- 循环执行所有的宏任务……执行一个微任务……所有的宏任务……一个微任务
- 第一次循环执行的整体代码属于宏任务