在 Promise 中使用 await

新手上路,请多包涵

必须将 Promise 的回调定义为异步似乎存在一些固有的错误:

 return new Promise(async (resolve, reject) => {
  const value = await somethingAsynchronous();
  if (value === something) {
    return resolve('It worked!');
  } else {
    return reject('Nope. Try again.');
  }
});

这显然是一种 反模式可能会产生编码问题。据我所知,即使将 await 语句放在 try / catch 块中,也更容易捕获错误。

我的第一个问题是,当一个人想要转发具有不同解析/拒绝值的 Promise 时,编写这样的代码的最佳方法是什么?然后/抓住? IE

 return new Promise((resolve, reject) => {
  somethingAsynchronous().then(value => {
    if (value === something) {
      return resolve('It worked!');
    } else {
      return reject('Nope. Try again.');
    }
  }); // errors would now be propagated up
});

还是按照 此处 的建议将其完全从 Promise 构造函数中取出?

 async function outerFunction() {
  const value = await somethingAsynchronous();
  return new Promise((resolve, reject) => {
    if (value === something) {
      return resolve('It worked!');
    } else {
      return reject('Nope. Try again.');
    }
  });
}

但是,如果您在 outerFunction() 中有多个 await 语句,即调用多个异步函数的线性代码块怎么办?那么你每次都必须创建并返回一个新的 Promise 吗?

但是你如何解释这样的代码呢?

 async function outerFunction() {
  if (someSynchronousCheck()) {
    return 'Nope. Try again.' // another reject case
  }

  const value = await somethingAsynchronous();
  // ...
}

我觉得我正在使它变得比它应该的更复杂。我试图避免嵌套回调/链接 then/catch 块,而不会在将来产生更多问题。

我的最后一个问题是,为什么回调传递给 Promise 不是固有的 async ?它已经包装在一个承诺中,并期望异步调用解析/拒绝函数。

原文由 Druckles 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.5k
2 个回答

你来做这件事:

 async function outerFunction() {
  const value = await somethingAsynchronous();
  if (value === something) {
    return 'It Worked!';
  }
  throw Error('Nope. Try again.');
}

使用 async outerFunction 用 Promise 包装 — 的结果。

如果您希望包装承诺解决某些问题,只需从 async 函数返回它。如果您希望包装承诺被拒绝,请在 async 函数中抛出一个错误。

但是你如何解释这样的代码呢?

 async function outerFunction() {
  if (someSynchronousCheck()) {
    throw Error('Nope. Try again.');
  }

  const value = await somethingAsynchronous();
  // ...
}

原文由 robertklep 发布,翻译遵循 CC BY-SA 3.0 许可协议

new Promise(async (resolve, reject) => { ... }) 是相对较新的反模式。它导致创建 2 个 promise 对象而不是 1 个,构造函数内部发生的未捕获错误不能被 try..catch 捕获并导致未处理的拒绝。

考虑到可以使用 async..await 处理 promise 异步代码, Promise 构造函数的当前用例是非 promise 异步代码,例如:

 new Promise(resolve => setTimeout(resolve, 1000))

Promise 构造函数包含同步代码或涉及其他承诺时,应使用 async 函数构造承诺。直接替换是 async IIFE:

 return (async (resolve, reject) => {
  const value = await somethingAsynchronous();
  if (value === something) {
    return 'It worked!';
  } else {
    throw 'Nope. Try again.';
  }
})();

如果需要 Promise 构造函数在与 async async 使用时仍然存在, Promise 构造函数应该向下移动 --- 函数。

我的最后一个问题是,为什么传递给 Promise 的回调不是天生异步的?它已经包装在一个承诺中,并期望异步调用解析/拒绝函数。

async 函数不仅仅是一个异步执行的函数,它返回另一个应该使用的承诺 - 或者至少用 catch 处理。 Promise 不应该使用从构造函数返回的承诺。

构造函数可以在同一刻度上解析并且不一定必须是异步的。

 Promise.resolve(1);

类似于

Promise(resolve => resolve(1))

而不是

Promise(resolve => setTimeout(() => resolve(1)))

原文由 Estus Flask 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏