一段JavaScript是如何执行的
- js事件循环
- 异步任务
- 异步任务队列
- 测试代码
- 结果调试
- 执行结果
js事件循环
当我们执行一行js代码时,如果是同步任务,就把它直接放到执行栈里面去执行,如果是异步任务,会把它放到一个异步的任务队列中,等待同步任务执行完,然后再从异步任务中读取异步任务.
异步任务
异步任务又分为 “宏任务” 和 “微任务”.
- 宏任务是宿主环境提供的. 例如
setTimeout()
以及正常的js脚本. - 微任务是由语言标准提供的. 像平时用的
promise
,nextTick
异步任务队列
异步任务队列里又有 “宏任务队列” 和 “微任务队列” ,如果同步任务执行完了,然后会先去执行微任务,会把所有的微任务执行完,才会去执行新的一轮宏任务.
测试代码
// 同步任务
console.log("script start");
// 异步任务 --- 宏任务
setTimeout(() => {
console.log("setTimeout1");
}, 0);
// 异步任务 --- 微任务 (如果是 new Promise()则是同步任务, 切记)
Promise.resolve()
.then(function () {
console.log("promise1");
})
.then(function () {
console.log("promise2");
});
// 异步任务---宏任务
setTimeout(() => {
console.log("setTimeout2");
}, 0);
// 同步任务
console.log("script end");
结果调试
执行console.log("script start");
因为它是同步代码所以立即打印 script start
执行到setTimeout()
时,因为它不是一个同步任务,所以会先将它放到异步任务队列中,等待同步任务执行结束才会执行.
同上
执行到console.log("script end");
时,因为是同步任务,所以立即输出 “script end”
现在同步任务已经处理完成, 接着就是处理异步任务. 因为 “宏任务” 执行顺序优先于 “微任务”, 所以会先去执行 Promise
异步队列宏任务处理完, 接着 去处理异步队列的 “微任务”
执行结果
script start
script end
promise1
promise2
setTimeout1
setTimeout2