为什么要将承诺包装在尝试/捕获块中?



我一直在通读 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);
}
});
}

我试图弄清楚为什么作者将承诺包装在尝试/请求块中。 为了解释,作者是这样说的:

请注意,对处理程序的调用必须包装在 try 块中,以确保它直接引发的任何异常都提供给回调。这很好地说明了使用原始回调正确处理错误的困难 - 很容易忘记正确路由这样的异常,如果不这样做,失败将不会报告给正确的回调。承诺使这主要是自动的,因此不易出错。

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

承诺使这变得更容易。可以解决它们(操作成功完成(或拒绝(操作失败(。解析处理程序(注册于 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)有关吗? 上面的示例是为了处理成功、具有失败响应的成功交付(例如使用不正确的请求类型(和完全失败的交付而构建的,所以也许它与此有关? 我在这里阅读了其他几个类似的问题,但我仍在努力将其应用于这些示例,因此非常感谢任何帮助。

请记住,handler函数是一个函数。 这意味着在将结果值传递给Promise.resolve之前调用和处理它

handler函数可能如下所示:

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

因此,它甚至不会进入Promise.resolve内部的"承诺世界"。这就是为什么需要使用try-catch结构的原因。因此,无论失败handler(承诺阶段还是函数处理(,都将由回调处理。

最新更新