不要在同步函数使用 await
async/await 可以接受同步函数,相当于 await Promise.resolve
,今天在个异步流程中发现一个同步函数使用了 await ,结果上没什么区别,但是会有性能损失。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| async function t1() { const data = [1, 2, 3]; const res = await data.map(val => val ** 2); return res; }
async function t2() { const data = [1, 2, 3]; const res = data.map(val => val ** 2); return res; }
console.time(1); t1().then(res => console.log(res)); console.timeEnd(1);
console.time(2); t2().then(res => console.log(res)); console.timeEnd(2);
|
性能对比:
1 2 3 4
| 1: 0.121ms 2: 0.055ms [ 1, 4, 9 ] [ 1, 4, 9 ]
|
不要使用 return await fn()
最近评审代码发现 return await fn()
这样的写法。其实这样写是多于的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| async function tmp0() { return await new Promise(res => { setTimeout(() => { console.log("tmp0"); res(1); }, 1000); }); }
async function tmp1() { const tmp = await new Promise(res => { setTimeout(() => { console.log("tmp1"); res(1); }, 1000); }); return tmp; }
async function tmp2() { return new Promise(res => { setTimeout(() => { console.log("tmp2"); res(1); }, 1000); }); }
async function test() { const [v0, v1, v2] = await Promise.all([tmp0(), tmp1(), tmp2()]); console.log(v0, v1, v2); }
test() .then(console.log) .catch(console.log);
|
输出
可以看到这里都能返回 1
如果这样使用在 ESLint 中会报错,no-retrun-await. 因为这是多于的。
捕获 await 错误的一个巧妙方式
在 async/await 函数中通常使用 try { await …} catch {} 的形式捕获 async 内部错误。
不过如果这个 await 后的函数不需要中断 async 函数,可以直接在 await 后使用 catch 即可。
1 2 3 4 5 6 7 8
| async function test() { await Promise.reject(0).catch(() => console.log(1)); return 4; }
test() .then(i => console.log("test.then => %s", i)) .catch(e => console.log("test.catch => %s", e));
|
输出:
注意,这里仅仅是说明这个 await 函数并不需要中断整体服务的情况下才可以。
这样的写法更为简洁。