Vit*_*lyB 17 javascript promise angularjs angular-promise
在以下代码中,$ q promise 的catch函数捕获异常:
// 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;
}
Run Code Online (Sandbox Code Playgroud)
但是,当我查看控制台日志输出时,我看到以下内容:

该异常是在Angular中捕获的,但也被浏览器的错误处理所捕获.此行为确实与Q库重现.
这是一个错误吗?我怎样才能真正捕获$ q的异常?
Ben*_*aum 16
Angular $q使用一种约定,无论被捕获,都会记录抛出的错误.相反,如果你想表示拒绝,你需要return $q.reject(...这样:
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;
}
Run Code Online (Sandbox Code Playgroud)
这是为了区分拒绝与SyntaxError之类的错误.就个人而言,这是一个我不同意的设计选择,但它是可以理解的,因为$q它很小,所以你无法真正构建一个可靠的未处理的拒绝检测机制.在像Bluebird这样强大的图书馆中,不需要这种东西.
作为旁注 - 永远不要抛出字符串:你会错过堆栈跟踪.
这是一个错误吗?
不.查看$ q的源代码可以看出,创建了一个故意的try/catch块来响应回调中抛出的异常.
deferred.reject...也被浏览器的错误处理所捕获
为了澄清,该异常不是由浏览器直接处理,而是因为Angular已调用而显示为错误 console.error
我怎样才能真正捕获$ q的异常?
回调在一段时间后执行,当前调用堆栈已清除,因此您将无法将外部函数包装在try/ catchblock中.但是,您有两个选择:
在回调中放入try/ catch阻止可能抛出异常的代码:
f1().then(function(data) {
try {
return f2();
} catch(e) {
// Might want convert exception to rejected promise
return $q.reject(e);
}
})
Run Code Online (Sandbox Code Playgroud)更改Angular $exceptionHandler服务的行为方式,例如如何覆盖$ exceptionHandler实现.您可能会将其更改为绝对没有任何内容,因此控制台的错误日志中永远不会有任何内容,但我认为我不会建议这样做.
这种行为的原因是未被捕获的错误与常规拒绝不同,例如,它可能由编程错误引起.实际上,这对用户来说是混乱或不受欢迎的,因为本机承诺或任何其他流行的承诺库都不会将抛出的错误与常规拒绝区分开来.(注意:虽然这种行为不符合Promises/A +规范,但也没有规定.)
$ Q:
由于e13eea,从promise
onFulfilled或onRejection处理程序抛出的错误被视为与常规拒绝完全相同.以前,它也会被传递给$exceptionHandler()(除了以错误为理由拒绝承诺).新行为适用于依赖的所有服务/控制器/过滤器等
$q(包括内置服务,如$http和$route).例如,$http's transformRequest/Response函数或路由的redirectTo函数以及路由的resolve对象中指定的函数将不再导致调用$exceptionHandler()它们是否抛出错误.除此之外,一切都会继续以同样的方式行事; 即承诺将被拒绝,路线转换将被取消,$routeChangeError事件将被广播等.
| 归档时间: |
|
| 查看次数: |
14827 次 |
| 最近记录: |