fe-learning
fe-learning copied to clipboard
关于async和await的“同步”
关于async和await的“同步”
题目
要求看代码写输出。
function wait(){
return new Promise(resolve =>
setTimeout(resolve, 10*1000)
)
}
async function func1() {
console.time('time-func1')
const x = await wait()
const y = await wait()
const z = await wait()
console.timeEnd('time-func1')
}
async function func2() {
console.time('time-func2')
const x = wait()
const y = wait()
const z = wait()
await x
await y
await z
console.timeEnd('time-func2')
}
func1()
func2()
/** 输出如下
* time-func2:10002.4ms
* time-func1: 32261.5ms
*/
解析
async、await语法糖让我们可以把Promise的异步回调处理写出“同步”的方式,即代码看起来是同步并且整洁很多,但其目的是简化使用多个 promise 时的同步行为,并非是真同步。
await 表达式会暂停当前 async function 的执行,等待 Promise 处理完成。若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,继续执行 async function。
如此相邻的两个 await wait() 会形成继发关系(串行)。要写成并发方式,~~可以如 func2函数所示用变量先缓存Promise,再一起执行~~,或者你也可以使用 Promise.all / Promise.allSettled,没有依赖关系的函数最好让它们同时触发。
注意:
Promise.all有短路效应,如果参数中promise有一个失败(rejected),此实例回调失败(reject),失败的原因是第一个失败promise的结果。
async function func3() {
console.time('time-func3')
await Promise.all([wait(),wait(),wait()])
console.timeEnd('time-func3')
}
func3()
// time-func3: 10455.867919921875ms
更多请参见: MDN-async function
这里的解析存在问题,真实情况应该是Promise constructor同步执行,await则会暂停当前async执行直到结果返回,相对而言,串行变成了并发。