先说结论:await 在等待一个“确切”的结果
总的来说,await 等待有两种情况:函数 和 其它值
一、等待函数返回值
1. 返回普通值
<script>
function func() {
// 返回 非 thenable 且 非 Promise - await 不额外等待 then
return 'aaa'
}
async function test() {
console.log(1);
await func()
console.log(3);
}
test();
new Promise(resolve => {
console.log(4)
resolve()
}).then(() => {
console.log(6)
}).then(() => {
console.log(7)
})
console.log(5);
// 最终输出:1 4 5 3 6 7
</script>
2. 返回 thenable 类型值 - 需额外等待一个 then
<script>
function func() {
// 返回 thenable - await 额外等待一个 then
return {
then(cb) {
cb()
}
}
}
async function test() {
console.log(1);
await func()
console.log(3);
}
test();
new Promise(resolve => {
console.log(4)
resolve()
}).then(() => {
console.log(6)
}).then(() => {
console.log(7)
})
console.log(5);
// 最终输出:1 4 5 6 3 7
</script>
3. 返回 Promise 对象
3.1 有结果且没有 then - 需额外等待两个 then,后来做了优化,无需额外等待
<script>
function func() {
// 返回有结果的 Promise 对象 - await 原来是要额外等待两个 then。后来做了优化,无需额外等待
return new Promise((resolve) => {
console.log('B')
resolve()
})
}
async function test() {
console.log(1);
await func()
console.log(3);
}
test();
new Promise(resolve => {
console.log(4)
resolve()
}).then(() => {
console.log(6)
}).then(() => {
console.log(7)
}).then(() => {
console.log(8)
}).then(() => {
console.log(9)
})
console.log(5);
// 最终输出:1 B 4 5 6 7 3 8 9
</script>
3.2 有结果且有 then - 待返回的 Promise 的 then 执行完后,还需额外等待两个 then。后来做了优化,无需额外等待
<script>
function func() {
// 返回有结果的 Promise 对象 - await 原来是要额外等待两个 then,后来做了优化,无需额外等待
return new Promise((resolve) => {
console.log('B')
resolve()
}).then(() => {
console.log("C")
}).then(() => {
console.log("D")
})
}
async function test() {
console.log(1);
await func()
console.log(3);
}
test();
new Promise(resolve => {
console.log(4)
resolve()
}).then(() => {
console.log(6)
}).then(() => {
console.log(7)
}).then(() => {
console.log(8)
}).then(() => {
console.log(9)
})
console.log(5);
// 最终输出:1 B 4 5 C 6 D 7 8 3 9
</script>
3.3 无结果 - await 后面的代码永远不会执行
<script>
function func() {
// 返回无结果的 Promise 对象
return new Promise(resolve => {
console.log("B")
// resolve() // 故意不产生结果,让这个 Promise 一直为 pending 状态,那么 log(3) 永远不会执行
})
}
async function test() {
console.log(1);
await func()
console.log(3);
}
test();
new Promise(resolve => {
console.log(4)
resolve()
}).then(() => {
console.log(6)
}).then(() => {
console.log(7)
}).then(() => {
console.log(8)
}).then(() => {
console.log(9)
})
console.log(5);
// 最终输出:1 B 4 5 C 6 D 7 8 3 9
</script>
二、等待其它值
1. 等待普通值 - 同函数返回普通值是一样的效果
2. 等待 thenable 类型值 - 同函数返回此类型值是一样的效果
3. 等待 Promise 对象
3.1 有结果且无 then - 这个不是等待 async 返回的 Promise,所以无需额外等待
<script>
async function test() {
console.log(1);
// 有结果,但这个不是等待 async 返回的 Promise,所以无需额外等待
await new Promise(resolve => {resolve()})
// await Promise.resolve() 是一个意思
console.log(3);
}
test();
new Promise(resolve => {
console.log(4)
resolve()
}).then(() => {
console.log(6)
}).then(() => {
console.log(7)
}).then(() => {
console.log(8)
}).then(() => {
console.log(9)
})
console.log(5);
// 最终输出:1 4 5 3 6 7 8 9
</script>
3.2 有结果且有 then - 这个不是等待 async 返回的 Promise,所以无需额外等待
<script>
async function test() {
console.log(1);
// 有结果
await new Promise(resolve => {
resolve()
}).then(() => {
console.log(10)
})
console.log(3);
}
test();
new Promise(resolve => {
console.log(4)
resolve()
}).then(() => {
console.log(6)
}).then(() => {
console.log(7)
}).then(() => {
console.log(8)
}).then(() => {
console.log(9)
})
console.log(5);
// 最终输出:1 4 5 10 6 3 7 8 9
</script>
3.3 无结果 - 和等待 async 返回无结果的 Promise 一样,await 后面的代码永远不会执行
那么问题来了,await 相当于什么?
来看以下代码,输出什么?
<script>
async function fun() {
console.log(2)
await "a"
console.log("A")
await "b"
console.log("B")
await "c"
console.log("C")
}
async function test() {
console.log(1)
await fun()
console.log(3)
}
test()
new Promise(resolve => {
console.log(4)
resolve()
}).then(() => {
console.log(5)
}).then(() => {
console.log(6)
}).then(() => {
console.log(7)
})
console.log(8)
</script>
答案是:1 2 4 8 A 5 B 6 C 7 3
再来看以下代码,输出什么?
<script>
async function fun() {
console.log(2)
return new Promise(resolve => {
resolve()
}).then(() => {
console.log("A")
}).then(() => {
console.log("B")
}).then(() => {
console.log("C")
})
}
async function test() {
console.log(1)
await fun()
console.log(3)
}
test()
new Promise(resolve => {
console.log(4)
resolve()
}).then(() => {
console.log(5)
}).then(() => {
console.log(6)
}).then(() => {
console.log(7)
})
console.log(8)
</script>
没错,和上面用 await 写的,输出结果一模一样
Note:
await
和Promise.prototype.then
虽然很多时候可以在时间顺序上能等效(如 fun 中的 await),但是它们之间有本质的区别(如 test 中的 await)。
test
函数中的await
会等待fun
函数中所有的await
取得 恢复函数执行 的命令并且整个函数执行完毕后才能获得取得 恢复函数执行 的命令;- test 函数的 await 此时不能在时间的顺序上等效 then,而要等待到 func 函数完全执行完毕;
- 比如这里的数字
3
很晚才输出,如果单纯看成then
的话,在下一个微任务队列执行时3
就应该作为同步代码输出了才对。