javascript - 优雅地处理 `await` ed Javascript Promise 上的拒绝

标签 javascript node.js asynchronous async-await es6-promise

ES2017 async/await 的一个很好的模式是:

async function () {
  try {
    var result = await some_promised_value()
  } catch (err) {
    console.log(`This block would be processed in
      a reject() callback with promise patterns
      but this is far more intuitive`)
    return false // or something less obtuse
  }
  result = do_something_to_result(result)
  return result;
}

能够处理这样的错误真是太好了。但是假设我想异步获取一个值,我想保护它不被重新分配(例如:数据库 session ),但我仍然想使用 async/await 模式(纯粹是因为我认为它更直观)。

以下内容不起作用,因为 const 是 block 作用域:

async function () {
  try {
    const result = await get_session()
  } catch (err) {
    console.log(`This block should catch any
      instantiation errors.`)
    return false
  }
  // Can't get at result here because it is block scoped.
}

当然,您可以在 try block 中执行该函数的其余部分,但是您可能会冒着被捕获的错误的风险,这些错误应该被遗漏到其他地方。 (例如,我在编写测试时遇到了这个挑战,其中测试失败之类的错误需要退回到测试套件,但想自己处理驱动程序实例化。也许我在这里陷入了某种反模式,因为不让这些错误退回到测试套件。)

简单的答案显然是不要在这里使用那种模式。改用 Promise 和回调。或者使用 var 并避免 block 范围的​​ constlet。但我喜欢重新分配保护和阻止范围的好处。

[问题]:Is there a way to wrap an await/async try/catch block to every function?似乎是一种潜在的解决方案,但不像 try/catch 那样可读。在我看来, try/catch 不会破坏函数范围并且我可以在 try/catch block 中使用 return 的事实更符合 async/await 的精神,为异步代码带来更具过程性的逻辑。

理想情况下,您希望执行 const x = await y() catch (err)const x = await y() || 之类的操作。失败但我想不出任何语法正确的类似流程。

更新: 正如@jmar777 所建议的,下面的另一种选择是:

const x = await y().catch(() => {/*handle errors here*/})

这可能是我在实践中发现的与最后两个示例最接近的。但它打破了上述示例中阻止下游执行的 return 范围。这是一种很好的类似同步的处理方式。

每个解决方案都有其权衡。

我已经在功能 block 顶部使用 let 手动提升变量作为工作解决方案(如 jmar777 的回答中所述)仍然是查看各种方法的一个有趣问题,所以我暂时让问题悬而未决。

最佳答案

您可能对使用 const 的好处有误解。使用 const 声明分配一个值不会使该值不可变,它只是意味着该常量的值不能更改或重新声明:

The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in case the content is an object, this means the object itself can still be altered. (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const)

在您的示例中,您最好手动在 try/catch 之外提升 result 绑定(bind):

async function () {
  let result;

  try {
    result = await get_session()
  } catch (err) {
    console.log(`This block should catch any
      instantiation errors.`)
  }

  // do whatever else you need with result here...
}

另一种方法是重构代码,使您根本不需要依赖 try/catch。例如:

async function () {
  const result = await get_session().catch(someRejectionHandler); 

  // do whatever else you need with result here...
}

请注意,您的下游代码需要优雅地处理 get_session() 被拒绝并且 result 未根据成功响应进行初始化的情况。这与您最初的示例没有什么不同,但在扫描代码时可能不那么明显。

关于javascript - 优雅地处理 `await` ed Javascript Promise 上的拒绝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41711671/

相关文章:

Javascript - 当页面使用 SSL 时复选框不起作用(使用 Kentico CMS)

javascript - 模块名称 "mysql"尚未加载上下文 : _. 使用 require([]) http ://requirejs. org/docs/errors.html#notloaded

javascript - 如何使用 npm 将 PDF.JS 导入 Typescript

c# - F# 异步 lambda 与 C# 异步模型互操作

javascript - JavaScript 不调用函数

javascript - 将 isDefaultPrevented() 与自定义事件结合使用

javascript - Three.js 光线拾取平面/网格面段 v69

node.js - express + socket.io + kubernetes Access-Control-Allow-Origin' header

c++ - SDL - 如何在不停止代码执行的情况下在 C++ 中异步播放音频?

java - 如何增加 AWS Lambda 客户端的超时