Promise.all和多个await的效率
约 4 分钟 #JavaScript
性能测试
笔者在项目中经常遇到需要同时开始多个异步任务的情况,但是不知道多个await和Promise.all的效率是否一样。
为此笔者写了以下的测试代码:
function createTask(delay) {
return () =>
new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, delay)
})
}
async function test() {
{
const st = Date.now()
for (let i = 0; i < 5; ++i) {
await createTask(1000)()
}
const time = Date.now() - st
console.log('多个await,但是在await之前不启动任务:' + time)
}
{
const st = Date.now()
const tasks = Array.from({ length: 5 }).map(createTask(1000))
for (const task of tasks) {
await task
}
const time = Date.now() - st
console.log('多个await,但是在await之前启动任务:' + time)
}
{
const st = Date.now()
const tasks = Array.from({ length: 5 }).map(createTask(1000))
await Promise.all(tasks)
const time = Date.now() - st
console.log('Promise.all: ' + time)
}
}
test()
最终输出:
多个await,但是在await之前不启动任务:5006
多个await,但是在await之前启动任务:1002
Promise.all: 1001
这表明:只要在await之前就执行了异步任务,那么使用多个await的效率跟Promise.all是一样的。
区别
虽然效率一样,但是使用Promise.all的时候,如果某一个任务失败了(抛出异常),那么其他没有执行完的任务会立马终止,这是因为Promise.all具有“快速失败”的行为^https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all#description。而多个await会将所有任务都执行完:
function createTask(delay) {
return () =>
new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error()) // throw Error
}, delay)
})
}
async function test() {
{
const st = Date.now()
for (let i = 0; i < 5; ++i) {
await createTask(1000)().catch(() => {})
}
const time = Date.now() - st
console.log('多个await,但是在await之前不启动任务:' + time)
}
{
const st = Date.now()
const tasks = [createTask(1000)(), createTask(2000)(), createTask(3000)()]
for (const task of tasks) {
await task.catch(() => {})
}
const time = Date.now() - st
console.log('多个await,但是在await之前启动任务:' + time)
}
{
const st = Date.now()
const tasks = [createTask(1000)(), createTask(2000)(), createTask(3000)()]
await Promise.all(tasks).catch(() => {})
const time = Date.now() - st
console.log('Promise.all: ' + time)
}
}
test()
输出为:
多个await,但是在await之前不启动任务:5007
多个await,但是在await之前启动任务:3001
Promise.all: 1001
