首页 > 解决方案 > 为什么要将 Promise 包装在 try/catch 块中?

问题描述

我一直在阅读 Eloquent JavaScript ,尤其是关于异步编程的这一章。我大部分时间都在理解它,但是其中一个例子让我迷失了。这是那个例子:

function requestType(name, handler) {
  defineRequestType(name, (nest, content, source,
                           callback) => {
    try {
      Promise.resolve(handler(nest, content, source))
        .then(response => callback(null, response),
              failure => callback(failure));
    } catch (exception) {
      callback(exception);
    }
  });
}

我试图弄清楚为什么作者将 Promise 包装在 try/request 块中。为了解释它,作者这样说:

请注意,对处理程序的调用必须包装在 try 块中,以确保将其直接引发的任何异常都提供给回调。这很好地说明了使用原始回调正确处理错误的难度——很容易忘记正确路由这样的异常,如果你不这样做,故障将不会被报告给正确的回调。Promise 使这大部分是自动的,因此不易出错。

但这让我感到困惑,因为就在不久之前,他说:

Promise 使这更容易。它们可以被解决(操作成功完成)或被拒绝(失败)。仅当操作成功时才​​调用解析处理程序(在 then 中注册),并且拒绝会自动传播到 then 返回的新承诺。并且当处理程序抛出异常时,这会自动导致其 then 调用产生的承诺被拒绝。因此,如果异步操作链中的任何元素失败,则整个链的结果将被标记为被拒绝,并且在失败点之外不会调用任何成功处理程序。

那么为什么我不能把它写成:

function requestType(name, handler) {
  defineRequestType(name, (nest, content, source,
                           callback) => {
      Promise.resolve(handler(nest, content, source))
        .then(response => callback(null, response),
              failure => callback(failure));
        .catch(reason => callback(reason));
  });
}

它与作者使用.then(response, failure)而不是有关.then(response).catch(failure)吗?上面这个例子是为了处理成功、失败响应的成功交付(比如使用了不正确的请求类型)和完全失败的交付,所以也许与此有关?我在这里阅读了其他几个类似的问题,但我仍在努力将其应用于这些示例,因此非常感谢任何帮助。

标签: javascriptasynchronouspromisetry-catch

解决方案


请记住,handler函数是函数。这意味着在将结果值传递给Promise.resolve

handler函数可能如下所示:

function handler(nest, content, source) { throw new Error(); }

因此,它甚至不会去里面的“无极世界” Promise.resolve。这就是为什么需要使用 try-catch 构造。所以无论失败(无论是承诺阶段还是handler函数处理)都将由回调处理。


推荐阅读