【问题标题】:How do you prevent throwing exceptions in functions that return promises?如何防止在返回 Promise 的函数中抛出异常?
【发布时间】:2018-01-13 15:27:18
【问题描述】:

返回承诺的函数不应该抛出异常,而是拒绝承诺,但确保始终如此的最佳做法是什么?例如,即使我有这样一个极其简单的类方法......

foo(x) {
  return this.promiseReturningApi.someMethod('bar', x);
}

...如果this.promiseReturningApi 未定义或someMethod 不是函数(除非它在promise 链中的第一个函数之后调用),则可能引发异常。

为了确保永远不会抛出异常,是否有必要始终使用这样的 try-catch 块:

foo(x) {
  try {
    return this.promiseReturningApi.someMethod('bar', x);
  } catch (e) {
    return Promise.reject(e);
  }
}

(或者使用Promise.resolve().then(() => this.promiseReturningApi.someMethod('bar', x))之类的东西) 对于任何将返回承诺的函数,或者如何确保不抛出异常?

【问题讨论】:

  • foo 是我给出的一个返回承诺的函数的示例,因为它只是返回返回承诺的函数的返回值。即便如此简单,foo 本身也可能抛出异常,那么是否有必要将 foo 的主体包围在 try-catch 块中?
  • 这就是 Bluebird Promise.try() 的用途。

标签: javascript promise es6-promise


【解决方案1】:

在返回 promise 的函数中,您可以使用 promise.catch(...) 就像这里提到的 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch 而不是 try/catch 包装器。这可能会让您只返回this.promiseReturningApi.someMethod('bar', x);

【讨论】:

  • 你的意思是在promiseReturningApi.someMethod内,应该用promise.catch(...)?但例如,如果 this.promiseReturningApi 未定义,则仍可能导致抛出异常。
【解决方案2】:

这是我认为最好的做法

/**in provider**/
foo(x) {
  return this.api.method(x); //Promise
}

/**in component**/
this.provider.foo('cat')
  .then((res) => { console.log(res) }) //resolved
  .catch((err) => { console.log(err) }) //rejected

【讨论】:

    【解决方案3】:

    冒着提交 `explicit promise constructor 反模式的风险,这会起作用:

    foo(x) {
      return new Promise(resolve => {
        resolve(this.promiseReturningApi.someMethod('bar', x));
      });
    }
    

    在没有抛出任何错误的情况下,这将按原样返回由promiseReturningAPi 产生的承诺。如果在任何地方抛出未捕获的错误,无论是出于何种原因在this.promiseReturningApi.someMethod 行中,或者甚至可能在调用链内部(例如在promiseReturningApi 内部,取决于它的编写方式),然后返回的承诺foo 将因为该错误原因被拒绝。这是由于“执行程序”(传递给new Promise的函数)中抛出的错误的处理方式的规范——即,它们导致被拒绝的承诺。

    但是,您应该仔细考虑是否真的想将本质上是程序逻辑错误(例如,缺少的someMethod)变成被拒绝的承诺。您可能会发现,让“真正的”错误成为错误、冒泡并被报告为错误并为失败的异步操作(例如网络请求失败)保留被拒绝的 Promise 是一种更好的程序结构。

    【讨论】:

    • 这是有道理的。我会留下 foo 没有 try-catch 或 Promise 构造函数。
    • 如果您没有 Bluebird 和 Promise.try(),那么就个人而言,我更喜欢 OP 自己对 Promise.resolve().then(() => this.promiseReturningApi.someMethod('bar', x))) 的建议,而不是这个闻起来像反模式的答案。
    猜你喜欢
    • 2018-12-23
    • 2022-01-07
    • 1970-01-01
    • 2017-12-04
    • 2020-04-06
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多