代码之家  ›  专栏  ›  技术社区  ›  Qiulang

等待承诺。拒绝还是抛出错误来纾困?

  •  2
  • Qiulang  · 技术社区  · 6 年前

    我正在将我的承诺链代码重构为异步/等待样式。这样做的原因之一是我希望一个catch块来处理所有错误情况(如本文所述 Understanding promise rejection in node.js )

    我的问题是当我遇到同步错误时,我应该打电话给 await Promise.reject throw error 为了挽救这个过程? 我知道哪种方法都有效,但我更喜欢 抛出错误 . 我已经知道我得到了一个无效的结果为什么我要等待?使用throw立即终止控制流似乎是更好的选择。

    我不是在谈论承诺链(我问题的全部要点),所以我不认为这条线 JavaScript Promises - reject vs. throw 回答了我的问题。

    我读了这篇文章 Error Handling in Node.js 我也不认为它能给出答案。但它确实说

    给定的函数应该传递操作错误,或者 同步(使用throw)或异步(使用回调或事件) 发射器) 但不是两者都有 . …一般来说,使用throw和expecting 使用try/catch的调用程序非常罕见…

    我的异步函数可能返回promise.reject。因此,我关心的是介绍两种方法来传递错误,就像文章所针对的那样。

    try {
       let result = await aysncFunc().
       if (!isResultValid(result)) { //isResultValid() is sync function 
          await Promise.reject('invalid result')
          //or throw 'invalid result'
       }
       ... //further processing
    }
    catch (error) {
      ...
    }
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Estus Flask    6 年前

    使用它在语义上是正确的 throw 在承诺控制流程中,这通常是摆脱承诺链的首选方法。

    根据编码样式, await Promise.reject(...) 可用于区分实际错误和预期拒绝。带字符串原因的拒绝承诺有效,但 throw 'invalid result' 被认为是可以解决的风格问题 linter rules 因为它是传统的 Error 实例作为异常。

    之所以重要,是因为字符串异常不能用 instanceof Error 而且没有 message 属性,一致性错误日志记录为 console.warn(error.message) 会导致模糊 undefined 条目。

    // ok
    class Success extends Error {}
    try {
      throw new Success('just a friendly notification');
    } catch (err) {
      if (!(err instanceof Success)) {
        console.warn(err.message);
        throw err;
      }
    }
    
    // more or less
    const SUCCESS = 'just a friendly notification';
    try {
      await Promise.reject(SUCCESS);
    } catch (err) {
      if (err !== SUCCESS)) {
        console.warn(err.message);
        throw err;
      }
    }
    
    // not ok
    try {
      throw 'exception';
    } catch (err) {
      if (typeof err === 'string') {
        console.warn(err);
      } else {
        console.warn(err.message);
      }
    
      throw err;
    }
    

    自从 invalid result 实际上是一个错误,合理的做法是:

      throw new TypeError('invalid result');
    

    我不是在谈论承诺链(我问题的全部要点),所以我不认为javascript承诺-拒绝和抛出线程回答了我的问题。

    async 函数是承诺链的语法糖,因此适用于承诺的所有点都适用于 异步的 也。

    有些情况下,抛出错误可能与拒绝承诺不同,但它们特定于其他承诺实现,如AngularJS。 $q 不要影响ES6承诺。同步误差 Promise 构造函数导致异常,这也不适用于 异步的 .