查看原文
其他

【第1459期】await VS return VS return await

司南free 前端早读课 2019-06-04

前言

看这篇应该不会错过站了。今日早读文章由美团@司南free翻译分享。

进入正文阅读前,听听来自@Alexl对前端五年来的感悟:

正文从这开始~

当编写异步函数的时候,await,return,return await三者之间有一些区别,从中选取正确的方式是很重要的。 我们从下面这个异步函数开始:

async function waitAndMaybeReject(){
   
// 等待1秒钟
   await
new Promise(resolve => setTimeout(resolve, 1000));
   
// 抛一枚硬币
   
const isHeads = Boolean(Math.round(Math.random()));
   
if(isHeads) return 'yay';
   
throw Error('Boo!');}

上面的函数会等待1秒钟后返回一个promise,然后有50%的机会成功返回yay或者抛出一个error。让我们用几种稍微不同的方式使用它。

直接调用

async function foo() {
   
try{
       waitAndMaybeReject
();
   
}catch(e){
       
return 'caught';
   
}}

在此处,如果调用了foo,返回的promise的状态始终都是resolved,值也永远是undefined,而且没有等待。

由于我们没有await,或者return waitAndMaybeReject()的结果,所以我们无法对它做出任何反应。像这样的代码通常是错误的。

Awaiting

async function foo(){
   
try{
       await waitAndMaybeReject
();
   
}catch(e){
       
return 'caught';
   
}}

在此处,如果调用了foo,返回的promise将始终等待1秒钟,然后结果要么状态为resolved,值为undefined,要么状态为reject d,值为”caught”。

因为我们等待了waitAndMaybeReject()的返回值,所以它的rejection会被返回并且被抛出(throw),catch的代码块就会执行。但无论如何,如果waitAndMaybeReject()没有报错而是顺利执行,我们依旧无法对它的返回值做任何事情。

Returning

async function foo() {
   
try {
       
return waitAndMaybeReject();
   
}
   
catch (e) {
       
return 'caught';
   
}}

在此处,如果调用了foo,返回的promise将始终等待1秒钟,然后结果要么是状态为resolved,值为”yaa”,要么是状态是reject,抛出错误Error(‘Boo!’)。

通过return waitAndMaybeReject()这行代码,我们直接传递了它的返回结果,所以我们的catch代码块永远不会执行。

Return-awaiting

如果你想在try代码块中得到带有正确返回值的resolved状态,在catch中捕获异常,那么正确的选择就是return await。

async function foo() {
   
try {
       
return await waitAndMaybeReject();
   
}
   
catch (e) {
       
return 'caught';
   
}}

在此处,如果调用foo,返回的promise将始终等待1秒钟,然后结果要么是状态为resolved,值为”yay”,要么是状态为resolved,值为”caught”

因为我们等待了waitAndMaybeReject()的结果,所以它的异常rejecttion会被返回并且被抛出(throw),catch的代码块就会执行。如果waitAndMaybeReject()顺利执行没有报错,就返它的结果。

如果对上面的内容还是觉着困惑,那么将代码拆分成两个步骤来看可能会比较好理解:

async function foo() {
 
try {
   
// 等待 waitAndMaybeReject() 的结果来解决,
   
// 并且将 fullfill 的值赋给 fullfilledValue:
   
const fulfilledValue = await waitAndMaybeReject();
   
// 如果 waitAndMaybeReject() reject了,
   
// 我们的代码就会抛出异常,并且进入 catch 代码块的逻辑。
   
// 否则,这里的代码就会继续运行下面的语句:
   
return fulfilledValue;
 
}
 
catch (e) {
   
return 'caught';
 
}}

Note: 在try/catch之外的代码块中执行return await是多余的(如前所述,直接return即可),甚至Eslint还专门有规则来检测这种场景,但是在try/catch代码块之内,Eslint就允许这种操作。

关于本文
译者:@司南free
译文:

https://juejin.im/post/5bf7baa1e51d4532206d5d92
作者:@Jake
原文:https://jakearchibald.com/2017/await-vs-return-vs-return-await/

最后,为你推荐


【第1094期】图与例解读Async/Await


【第1028期】理解 JavaScript 的 async/await


【第1455期】新一代页面生命周期API:来自Chrome官方博客的介绍

Modified on

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存