首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >AngularJS - Promises重新抛出捕获的异常

AngularJS - Promises重新抛出捕获的异常
EN

Stack Overflow用户
提问于 2014-04-27 23:01:07
回答 5查看 15.6K关注 0票数 18

在下面的代码中,promise的$q catch函数捕获了一个异常:

代码语言:javascript
复制
// Fiddle - http://jsfiddle.net/EFpn8/6/
f1().then(function(data) {
        console.log("success 1: "+data)
        return f2();
    })
    .then(function(data) {console.log("success 2: "+data)})
    .catch(function(data) {console.log("error: "+data)});

function f1() {
    var deferred = $q.defer();
    // An exception thrown here is not caught in catch
    // throw "err";
    deferred.resolve("done f1");        
    return deferred.promise;
}

function f2() {
    var deferred = $q.defer();
    // An exception thrown here is handled properly
    throw "err";
    deferred.resolve("done f2");        
    return deferred.promise;
}  

但是,当我查看控制台日志输出时,我看到了以下内容:

异常是在Angular中捕获的,但也是由浏览器的错误处理捕获的。这种行为在Q库中也会重现。

这是个bug吗?如何才能真正捕获$q的异常?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2017-02-15 21:31:08

已在AngularJS 1.6版中修复

这种行为的原因是,未捕获的错误与常规拒绝不同,例如,它可能是由编程错误引起的。在实践中,这对用户来说是令人困惑或不受欢迎的,因为本机promise和任何其他流行的promise库都不能区分抛出的错误和常规的拒绝。(注意:虽然此行为不违反Promises/A+规范,但也没有规定。)

$q:

由于e13eea,从promise的onFulfilledonRejection处理程序抛出的错误与常规拒绝完全相同。以前,它也会被传递给$exceptionHandler() (除了以错误为理由拒绝承诺之外)。

新的行为适用于所有依赖于$q的服务/控制器/过滤器等(包括内置服务,如$http$route)。例如,如果抛出错误,$http's transformRequest/Response函数或路由的redirectTo函数以及在路由的resolve对象中指定的函数将不再导致对$exceptionHandler()的调用。除此之外,一切都将继续以相同的方式运行;即,承诺将被拒绝,路线转换将被取消,$routeChangeError事件将被广播等。

-- AngularJS Developer Guide - Migrating from V1.5 to V1.6 - $q

票数 5
EN

Stack Overflow用户

发布于 2014-04-27 23:24:16

Angular的$q使用一种约定,即无论是否被捕获,抛出的错误都会被记录下来。相反,如果你想发出拒绝的信号,你需要这样return $q.reject(...

代码语言:javascript
复制
function f2() {
    var deferred = $q.defer();
    // An exception thrown here is handled properly
    return $q.reject(new Error("err"));//throw "err";
    deferred.resolve("done f2");        
    return deferred.promise;
}  

这是为了区分拒绝和像SyntaxError这样的错误。就我个人而言,这是一个我不同意的设计选择,但这是可以理解的,因为$q很小,所以你不能真正构建一个可靠的未处理的拒绝检测机制。在像Bluebird这样更强大的库中,这类事情不是必需的。

顺便说一句--永远,永远不要抛出字符串:那样你就会错过堆栈跟踪。

票数 16
EN

Stack Overflow用户

发布于 2014-04-28 00:00:25

它是一个bug吗?

不是的。查看source for $q会发现,创建了一个特意创建的try / catch块来响应在回调中引发的异常

  1. 拒绝了这个承诺,因为您已经通过注册的Angular异常处理程序调用了deferred.reject
  2. Calling。正如可以在$exceptionHandler docs中看到的,默认行为是将其作为错误记录到浏览器控制台,这就是您所观察到的。

...也被浏览器的错误处理捕获。

为了澄清,这个异常不是由浏览器直接处理的,而是作为一个错误出现的,因为Angular调用了console.error

如何才能真正用$q捕获异常?

回调将在一段时间后执行,此时当前调用堆栈已清除,因此您将无法将外部函数包装在try / catch块中。但是,您有两个选项:

  • 在回调中将可能抛出异常的代码放在try/catch块中:

您可以将其更改为完全不执行任何操作,这样控制台的错误日志中就不会有任何内容,但我不建议这样做。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23324942

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档