js代码执行顺序
1、同步代码会按照顺序执行,发现异步代码会根据类型分别放入宏队列和微队列
宏队列macrotask,也叫tasks,其中包含
- setTimeout
- setInterval
- setImmediate (Node独有)
- requestAnimationFrame (浏览器独有)
I/O - UI rendering (浏览器独有)
微队列microtask,也叫jobs,其中包含
- process.nextTick (Node独有)
- Promise
- Object.observe
- MutationObserver
2、同步代码执行完之后调用栈Stack会清空。
3、然后按顺序取出微队列中的任务放入调用栈Stack中执行,直到把微队列中的任务执行完毕。若执行过程中又产生了微队列的任务,那么会排在本次执行的微队列后面在本次执行。
4、微队列执行完毕后,微队列microtask和调用栈Stack都为空队列。
5、接着取出宏队列中的首个任务放入调用栈Stark中执行。
6、重复执行1-5步骤。
举个列子:
console.log(1);
setTimeout(() => {
console.log(2);
Promise.resolve().then(() => {
console.log(3)
});
});
new Promise((resolve, reject) => {
console.log(4)
resolve(5)
}).then((data) => {
console.log(data);
})
setTimeout(() => {
console.log(6);
})
console.log(7);
输出结果:
1
4
7
5
2
3
6
根据上面所讲的分析下此块代码:
1、首先毫无疑问的输出第一行同步代码 1。
2、按顺序执行遇见setTimeout,放入宏队列,此时
- 宏队列任务:
let macrotask =
[
setTimeout(() => {
console.log(2);
Promise.resolve().then(() => {
console.log(3)
});
})
]
- 微队列任务:
let microtask = []
3、继续往下执行遇见Promise,会同步执行Promise内的代码,.then()的回调会被放入微队列中,执行到这里输出1 4,此时:
- 宏队列任务:
let macrotask =
[
setTimeout(() => {
console.log(2);
Promise.resolve().then(() => {
console.log(3)
});
})
]
- 微队列任务:
let microtask =
[
(5) => {
console.log(5);
}
]
4、继续往下执行又遇见定时器,放入宏队列,无新输出,输出还为1 4,此时:
- 宏队列任务:
let macrotask =
[
setTimeout(() => {
console.log(2);
Promise.resolve().then(() => {
console.log(3)
});
}),
setTimeout(() => {
console.log(6);
})
]
- 微队列任务:
let microtask =
[
(5) => {
console.log(5);
}
]
5、继续执行console.log(7),输出1 4 7,宏队列、微队列为变化。
6、同步任务执行完毕,开始按顺序执行微队列任务输出5,这个周期微队列清空,现在输出1 4 7 5,此时:
- 宏队列任务:
let macrotask =
[
setTimeout(() => {
console.log(2);
Promise.resolve().then(() => {
console.log(3)
});
}),
setTimeout(() => {
console.log(6);
})
]
- 微队列任务:
let microtask = []
7、同步任务以及微队列任务执行完毕,开始执行宏队列首个任务重复以上操作,先执行console.log(2)打印出2,接着遇见Promise加入微队列,目前输出1 4 7 5 2,此时:
- 宏队列任务:
let macrotask =
[
setTimeout(() => {
console.log(6);
})
]
- 微队列任务:
let microtask =
[
() => {
console.log(3)
}
]
8、该周期同步任务执行完毕,执行微队列任务打印3,现在输出1 4 7 5 2 3,此时微队列实行完毕,继续执行宏队列首任务,此时
- 宏队列任务:
let macrotask =
[
setTimeout(() => {
console.log(6);
})
]
- 微队列任务:
let microtask = []
9、执行微队列首个任务console.log(6),打印出6,此时输出1 4 7 5 2 3 6,此时宏队列、微队列和执行栈都执行完毕清空,本次代码执行完毕。