【问题标题】:Do promises in AngularJS catch every exception/error?AngularJS 中的 Promise 会捕获每个异常/错误吗?
【发布时间】:2015-10-19 03:47:46
【问题描述】:

我在工作中继承了一个代码库,其中包含十几个以下模式的示例:

var promise = null;
try {
    promise = backendService.getResults(input);
}
catch (exception) {
    console.err(exception);
}
if (promise !== null) {
    promise.then(function (response) {
        // do stuff
    })
    .catch(function (error) {
        console.err(error);
    });
}

backendService 是一个 Angular 服务,它又通过 $http 调用一个 REST 服务。

所以我的问题是:try/catch 真的有必要吗?是否会出现任何引发特定错误/异常而 Promise 的 .catch 无法捕获的情况?

这一直是整个上午团队争论的主题,我们提出的唯一解决方案是我们不认为这是必要的,但是 (a)更改它会破坏与它一起编写的测试(这也需要更改),并且(b)好吧......这是防御性编码,对吗?这不是一件坏事。

不过,当有更重要的事情要做时,真正费心将其重构为遗忘的好处并不是我要问的。我只是想知道当像这样传递承诺时(特别是在 AngularJS 中,如果这会产生影响),这是否是一种合理的模式,或者只是偏执狂。

【问题讨论】:

  • 不需要。你只能有你的then()catch()
  • 在我看来它只是部分有用。如果您的代码中有异常触发 XHR(大概)以获取结果,则此代码将捕获,但通常该代码更为人所知,并且不受运行时异常的影响。棘手的部分是来自服务器的响应——由于服务返回了您没想到的东西,您更有可能在那里遇到异常。这将由 Promise 拒绝处理。如果您在服务中安全(通常)处理input,我认为没有必要尝试/捕获。
  • 测试起来相对容易。首先在各种方法中引入语法错误,包括在 $h​​ttp 调用之前和回调内部,然后测试 http 错误,例如 404 500 和 CORS 错误。我的假设是 .catch 在 http 请求启动并返回 promise 之后捕获所有内容,但不是在此之前。

标签: javascript angularjs promise


【解决方案1】:

AngularJS 中的 Promise 会捕获所有异常/错误吗?

没有。只有从 then/catch callbacks 内部抛出的异常会被自动捕获。在它们之外发生的所有错误都需要明确处理。

是否会出现任何引发特定错误/异常而 Promise 的 .catch 无法捕获的情况?

是的。 backendService.getResults(input) 调用可能不会返回一个承诺,但它可能会引发异常。或者当backendService 为空时,它甚至不会走那么远,你会得到一个ReferenceError.getResults 不是一个函数,你会得到一个TypeError

try/catch 真的有必要吗?

不是真的。在后一种情况下,你的代码有一个严重的错误,你可能不关心抛出和崩溃。 backendService.getResults(input) 抛出的前一种情况被严重鄙视。 Asynchronous functions should never throw 但只返回承诺 - 正是因为您不必编写两个错误处理语句。

嗯...这是防御性编码,对吧?这不是一件坏事。

是的,差不多。但这里值得怀疑。同步异常在这里真的出乎意料,而不仅仅是可以处理故障的服务。 catch 块中的日志消息应该表明这一点。

请注意,它的防御性也不够。它没有捕捉到getResults() 确实返回的可能更可能的错误,但这不是一个承诺。调用 .then() 可能会抛出。同样,if (promise !== null) 是可疑的,因为当错误返回null 时它会隐藏(我们真的可能需要try-catch-else)。

【讨论】:

  • 到你的最后一段:对不起,那是我的错误。我已经在我的问题中编辑了代码块以澄清。在尝试之前声明promise实际上是将其初始化为null
  • 给其他人。谢谢,这和我想的差不多。 backendService 现在和调用它的代码一样在我的控制之下,我可以告诉你,它绝对会返回一个承诺,并且只有在发生灾难性且几乎不可能发生的事情时才会 throw。就像整个文件被排除在构建之外。它包含单词throw,如果包含,我会出于您描述的原因将其删除。顺便说一句,我喜欢“极度鄙视”这个词。它非常适合。
【解决方案2】:

try/catch 真的有必要吗?

不是真的。只要您的backendService.getResults() 返回一个承诺。赞return $http(...)

是否会出现任何特定错误/异常的情况 抛出 promise 的 .catch 无法捕获?

我不这么认为,因为任何错误都会被拒绝,它会落入你的.catch()处理程序

嗯...这是防御性编码,对吧?这不是一件坏事。

这取决于... Javascript try/catch 存在一些性能问题。因此,如果您只是为了确保而使用,则可以将其删除:)

如果您愿意,可以在此处进一步查看 try-catch 讨论:Javascript Try-Catch Performance Vs. Error Checking Code

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-14
    • 2015-03-16
    • 2015-06-11
    • 2014-03-21
    • 1970-01-01
    • 2010-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多