javascript return了还继续走 js return await_web


文章目录

  • JavaScript中'return await promise' 和 'return promise'
  • 1、Same behavior(相同的行为)
  • 2、Different behavior(不同的行为)
  • 3、Conclusion(总结)


 

JavaScript中’return await promise’ 和 ‘return promise’

当从异步函数的 promise 返回结果时,你可以等待该 promise 执行完再return await promise,也可以直接返回return promise

async function func1() {
  const promise = asyncOperation();
  return await promise;
}

// vs
async function func2() {
  const promise = asyncOperation();
  return promise;
}

你很快就会看到这两个表达式都可以有效执行。

但是,是否存在这些表达式表现不同的情况? 让我们来了解一下!

1、Same behavior(相同的行为)

为了找出这两个表达式之间的区别(return await promisereturn promise),将使用一个辅助函数promisedDivision(n1, n2)。该函数对 2 个参数进行除法计算,并返回包装在一个Promise中的结果:

function promisedDivision(n1, n2) {
  if (n2 === 0) {
    return Promise.reject(new Error('Cannot divide by 0'));
  } else {
    return Promise.resolve(n1 / n2);
  }
}

如果第二个(除数)参数为 0,该函数将返回一个Promisereject,因为除以 0 是不可能的。

好的,定义了辅助函数,让我们对一些数字进行除法计算。

以下函数divideWithAwait()使用return await promiseDivision(6, 2) 表达式返回包装在promise 中的6 除以2的结果:

async function divideWithAwait() {
  return await promisedDivision(6, 2);
}

async function run() {
  const result = await divideWithAwait();
  console.log(result); // logs 3
}
run();

run()函数内部,等待divideWithAwait()执行完返回结果,而divideWithAwait()内部中等待promisedDivision(6, 2)执行完返结回结果。一切正常。

现在让我们尝试使用没有await关键字的第二个表达式,并直接返回包装了除法结果的promise返回promiseDivision(6, 2)

async function divideWithoutAwait() {
  return promisedDivision(6, 2);
}

async function run() {
  const result = await divideWithoutAwait();
  console.log(result); // logs 3
}
run();

即使在divideWithoutAwait()中不使用await关键字,run()函数中的表达式divideWithoutAwait()仍然正确地将6 / 2 除法计算为3!

在这一步,您已经看到使用return await promisereturn promise没有区别。 至少在处理成功的Promise时。

但让我们进一步探索!

2、Different behavior(不同的行为)

现在让我们采取另一种方法,特别是尝试处理执行Promise.reject时。 为了让函数promiseDivision(n1, n2) 返回一个rejectpromise,我们将第二个参数设置为 0。

因为promiseDivision(n1, 0)现在将返回reject,让我们将执行过程放在try {... } catch (error) {...}中进行——以查看是否捕获了rejectpromise

好的,让我们使用带有await关键字的return await promiseDivision(5, 0)表达式:

async function divideWithAwait() {
  try {
    return await promisedDivision(5, 0);
  } catch (error) {
    // Rejection caught
    console.log(error); // logs Error('Cannot divide by 0')
  }
}

async function run() {
  const result = await divideWithAwait();
  console.log(result); // logs undifined
}
run();

因为除以零是不可能的,所以promiseDivision(5, 0)返回一个reject的 promise。catch(error) { ... }成功捕获了由 promiseDivision(5, 0)抛出的reject的 promise。

省略await的第二种方法呢?

async function divideWithoutAwait() {
  try {
    return promisedDivision(5, 0);
  } catch (error) {
    // Rejection NOT caught
    console.log(error);
  }
}

async function run() {
  const result = await divideWithoutAwait();
}
run(); // Uncaught Error: Cannot divide by 0

然而,这一次catch(error) { ... }没有捕获rejectpromise

现在您可以很容易地看到使用return await promisereturn promise之间的主要区别:

When being wrapped into try { ... }, the nearby catch(error) { ... } catches the rejected promise only if the promise is awaited (which is true for return await promise).

当被放入try {... } catch (error) {...}时,仅仅如果promiseawait修饰时(return await promise),最近的catch(error) { ... }将会捕获promisereject结果!

3、Conclusion(总结)

在大多情况下,特别是Promise返回成功的结果(resolve)时,return await promise and return promise并没有多大的区别。

然而、如果你想要从一个异步函数的1返回结果中捕捉promisereject结果,你应该明确的使用return await promise表达式并且有意的用await修饰!

try {...catch(error) {...} 语句只能捕获等待执行以后的rejectpromise结果!