偶然间看到下面这道题,是考察async...await
机制的,我觉得还挺有意思的。你可以试试不借助控制台自己在心里推算一下运行结果。
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 37 38 const Err = async () => { throw new Error (42 ); }; const Obj = { async A (){ try { return Err(); } catch { console .log('A' ); } }, async B (){ try { await Err(); } catch { console .log('B' ); } }, async C (){ try { Err(); } catch { console .log('C' ); } }, }; ( async () => { for ( const key in Obj ) { try { await Obj[key](); } catch { console .log('D' ); } } } )();
放一张图防止你们不小心看到答案。
先说答案,分别打印D
和B
,最后报错Uncaught (in promise) Error: 42
我总结了一下,这题主要考察了以下知识点:
async
函数总是返回一个promise这个promise是什么,分为以下情况:
函数体内抛出了错误,则函数执行结果为这个错误的Promise.reject()
包装对象
如果函数体内返回了一个promise,则函数执行结果就是这个promise。
否则,函数执行结果为函数体内返回值的Promise.resolve()
包装对象。有一种情况容易让人混淆:函数体return new Erro(1)
,则执行结果相当于Promise.resolve(new Error(1))
,注意return new Error(1)
和throw new Error(1)
的区别。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 async function fn1() { throw new Error(1) } async function fn2() { return Promise.reject(1) } async function fn3() {} async function fn4() { return new Error(1) } fn1() // Promise {<rejected>: Error: 1} fn2() // Promise {<rejected>: 1} fn3() // Promise {<fulfilled>: undefined} fn4() // Promise {<fulfilled>: Error: 1}
await
在等待解开一个promise,等不来就报错上面的标题是为了简短一点,可能描述地不是很准确,我会拆分成几点来说明:
await
后总是跟一个promise,如果后面跟的不是promise,会用Promise.resolve()
包装一下。
如果await
表达式后跟一个fulfilled
态的promise,会返回对应的值。
如果await
表达式后跟一个rejected
态的promise,会抛出错误,可以用.catch()方法
或try...catch
块捕获。
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 async function fn1 ( ) { const res = await Promise .resolve(1 ) console .log(res) } async function fn2 ( ) { const res = await new Error (1 ) console .log(res) } async function fn3 ( ) { const res = await Promise .reject(1 ) console .log(res) } fn1() fn2() fn3() async function fn3 ( ) { const res = await Promise .reject(1 ).catch(e => { console .log(e) }) } async function fn3 ( ) { try { const res = await Promise .reject(1 ) } catch (e) { console .log(e) } }
了解了上面的知识点,我们就可以分析代码了,我把代码解释放在了下面的代码注释中,这样看起来应该更清晰一点:
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 const Err = async () => { throw new Error (42 ); }; const Obj = { async A (){ try { return Err(); } catch { console .log('A' ); } }, async B (){ try { await Err(); } catch { console .log('B' ); } }, async C (){ try { Err(); } catch { console .log('C' ); } }, }; ( async () => { for ( const key in Obj ) { try { await Obj[key](); } catch { console .log('D' ); } } } )();