同步任务和异步任务(微任务和宏任务)
JavaScript是一门单线程语言
分为同步任务和异步任务
-
同步任务是指在主线程上排队执行的任务,
只有前一个任务执行完毕,才能继续执行下一个任务。 -
异步任务指的是,不进入主线程、而进入"任务队列"的任务
只有等主线程任务全部执行完毕,"任务队列"的任务才会进入主线程执行。
而异步任务分为宏任务和微任务
-
macro-task(宏任务):包括整体代码script,setTimeout,setInterval
-
micro-task(微任务):Promise,process.nextTick
(Promise并不是完全的同步,在Promise中是同步任务,执行resolve或者reject回调的时候,此时是异步操作,会先将then/catch等放到异步任务中的微任务队列)
执行过程:
1.先执行所有同步任务,碰到异步任务放到任务队列中
2.同步任务执行完毕,开始执行当前所有的异步任务
3.先执行任务队列里面所有的微任务
4.然后执行一个宏任务
5.然后再执行所有的微任务
6.再执行一个宏任务,再执行所有的微任务·······依次类推到执行结束。
3-6的这个循环称为事件循环Event Loop
事件循环是JavaScript实现异步的一种方法,也是JavaScript的执行机制
简单分析下这个代码:
//1
console.log('1');
//2
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
//3
process.nextTick(function() {
console.log('6');
})
//4
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
//5
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
- 先执行1 输出1
- 执行到2,把setTimeout放入异步的任务队列中(宏任务)
- 执行到3,把process.nextTick放入异步任务队列中(微任务)
- 执行到4,上面提到promise里面是同步任务,所以输出7,再将then放入异步任务队列中(微任务)
- 执行到5,同2
- 上面的同步任务全部完成,开始进行异步任务
- 先执行微任务,发现里面有两个微任务,分别是3,4压入的,所以输出6 8
- 再执行一个宏任务,也就是第一个setTimeout
- 先输出2,把process.nextTick放入微任务中,再如上promise先输出4,再将then放入微任务中
- 再执行所以微任务输出输出3 5
- 同样的,再执行一个宏任务setTImeout2,输出9 11 在执行微任务输出10 12
- 所以最好的顺序为:1 7 6 8 2 4 3 5 9 11 10 12
欢迎指正!