请写出下面代码的输出结果
async function promise1() {
console.log("promise1 start")
await promise2()
console.log("promise1 end")
}
function promise2() {
console.log("promise2")
}
setTimeout(function () {
console.log("setTimeout")
}, 0)
console.log("script start")
promise1()
new Promise((resolve, reject) => {
console.log("Promise")
resolve()
}).then(function () {
console.log("Promise then")
})
console.log("script end")
解析:
- 宏任务/微任务
- 事件循环
- promise, async/await
宏任务/微任务
宏任务包含
script(整体代码)
setTimeout
setInterval
I/O
UI交互事件
postMessage
MessageChannel
setImmediate(Node.js 环境)
微任务包含
Promise.then
Object.observe(将要废弃)
MutaionObserver(新特性)
process.nextTick(Node.js 环境)
事件循环
- js是单线程,一个线程拥有唯一一个时间循环,但任务队列可以有多个。
- 任务队列又分为宏任务和微任务。
- 来自不同任务源的任务会进入到不同的任务队列。(setTimeout与setInterval是同源的)
- 事件循环的顺序,决定了JavaScript代码的执行顺序。它从script(整体代码)开始进入第一次循环,代码一行一行执行,执行过程中遇到宏任务,把宏任务加到宏任务队列中, 遇到微任务放到微任务队列中,当宏任务的函数调用栈执全部执行后,去看有没有微任务, 如果有,去执行微任务, 微任务全部执行完成后,循环再次从宏任务开始,这样循环。
- 浏览器为了能够使得JS内部(macro)task与DOM任务能够有序的执行,会在一个(macro)task执行结束后,在下一个(macro)task 执行开始前,对页面进行重新渲染,流程:宏任务->微任务->渲染->宏任务->微任务->渲染->...
promise, async/await
- promise是同步的,它里面的代码会同步执行。
- promise.then是微任务,promise.then里面的代码放到微任务队列中,等宏任务执行完成之后执行。
- async/await 是同步语法,解决异步回调问题,promise.then.catch 链式调用,但也是基于回调函数的。
- await会等待一个函数的执行结果,这个函数式同步的
- await下面的代码相当于promise.then也会放到微任务队列中。
揭晓答案
async function promise1() {
console.log("promise1 start")
await promise2()
console.log("promise1 end")
}
function promise2() {
console.log("promise2")
}
setTimeout(function () {
console.log("setTimeout")
}, 0)
console.log("script start")
promise1()
new Promise((resolve, reject) => {
console.log("Promise")
resolve()
}).then(function () {
console.log("Promise then")
})
console.log("script end")
------------------------------------
script start
promise1 start
promise2
Promise
script end
promise1 end
Promise then
setTimeout