Angular 1.6 中可能未处理的拒绝
Possibly unhandled rejection in Angular 1.6
我有一个代码 AngularJS:
service.doSomething()
.then(function(result) {
//do something with the result
});
在 AngularJS 1.5.9 中,当我在 .then()
部分出现错误时,例如:
service.doSomething()
.then(function(result) {
var x = null;
var y = x.y;
//do something with the result
});
我收到了明确的错误消息:
TypeError: Cannot read property 'y' of null
但是在使用相同代码的 1.6 版本中,我遇到了不同的错误:
Possibly unhandled rejection: {} undefined
我知道这个跟this change有关,解决方案很简单,加.catch()
块:
service.doSomething()
.then(function(result) {
var x = null;
var y = x.y;
//do something with the result
})
.catch(console.error);
现在我又得到了我想要的东西:
TypeError: Cannot read property 'y' of null
但是如何在不在每个地方添加 .catch()
块的情况下为整个应用程序获得相同的结果(更详细的错误)?
我测试了建议的解决方案,通过添加以下内容来禁用此功能:
$qProvider.errorOnUnhandledRejections(false);
但情况更糟 - 我在控制台中没有任何东西!错误被吞没在某个地方,根本没有记录。我不确定 AngularJS 1.6 或我的配置是否有问题。
您是否知道如何 "restore" 从版本 1.5.9 开始记录行为?
编辑:
添加自定义错误处理程序:
.factory('$exceptionHandler', function($log) {
return function(exception, cause) {
$log.warn(exception, cause);
};
})
一点帮助也没有。在错误处理程序中,我已经收到 "wrapped" 错误。
此问题已通过 fix($q): Add traceback to unhandled promise rejections -- Commit 316f60f and the fix is included in the v1.6.1 release 解决。
即使在我的 httpErrorInterceptor 中使用版本 1.6.1 我也有问题,对于一个用例,如果我的 api return 404 我必须尝试使用其他数据的另一个请求......所以在在这种情况下,我只拒绝请求并且 angular 抛出未处理的拒绝错误...
我安装了 1.5.9,现在没有错误了!
我通过将 angular-ui-router 升级到 0.3.2 解决了版本 1.6.1 中的相同问题。
还有另一种情况,将 finally()
处理程序添加到 promise 会产生错误:
http://plnkr.co/edit/eT834BkIEooAMvrVcLDe
因为 finally()
创建了一个新的承诺并在其上调用了解析器。 (在拒绝案例中拒绝第二个)
我已经在 plnkr 中进行了修复,但看起来不太好。
当 angular-ui-router (ui-sref) 使用 angular ver1.6.1 未处理被拒绝的承诺时,我遇到了相同的未处理拒绝错误 & 默认情况下启用此功能。
对于任何想要解决方法的人(尽管不推荐),您可以像这样在全局范围内阻止未处理的承诺拒绝 —
app.config(['$qProvider', function ($qProvider) {
$qProvider.errorOnUnhandledRejections(false);
}]);
errorOnUnhandledRejections(假);对我来说不是解决方案。
您确实需要定义异常处理程序...但是...将其包装在超时函数中:这将强制抛出原始 exception/stack 跟踪。
要使错误在 Web 控制台中显示为错误,如您最初预期的那样:
ng.factory('$exceptionHandler', function($log) {
return function(exception, cause) {
// do some some stuff...
setTimeout(function(){
// throw the original exception (with correct line #'s etc)
throw exception;
})
};
});
这里是超时技巧:
Why can I not throw inside a Promise.catch handler?
我通过在 catch 块中添加默认值解决了这个错误,例如:
service.doSomething()
.then(function(response) {
var x = null;
var y = x.y;
}).catch(function(error) {
var y = 0;
});
(考虑到我不是经验丰富的 angular 开发人员)
第一个选项只是按照建议 Cengkuru Michael:
在 $qProvider 配置中使用 disablinconfiguring errorOnUnhandledRejections
隐藏错误
app.config(['$qProvider', function ($qProvider) {
$qProvider.errorOnUnhandledRejections(false);
}]);
BUT 这只会关闭日志记录。错误本身将保持
在这种情况下,更好的解决方案 将是 - 使用 .catch()
方法处理拒绝:
service.doSomething()
.then(function (response) {})
.catch(function (err) {});
有用的链接:
此信息帮助我追踪(在我的例子中)创建承诺而不是添加错误处理程序的内容。我发现它隐藏在问题 #2889 "Possibly unhandled rejection with Angular 1.5.9".
的讨论中
要点是,补丁 $q
缓存创建承诺时的堆栈跟踪,以便在触发错误时可以检索它。
为此,请插入此代码以装饰 $q
靠近 angular 应用顶部的某个位置:
// Decorate the $q service when app starts
app.decorator('$q', ["$delegate", function($delegate) {
// Create a new promise object
var promise = $delegate.when();
// Access the `Promise` prototype (nonstandard, but works in Chrome)
var proto = promise.__proto__;
// Define a setter for `$$state` that creates a stacktrace
// (string) and assigns it as a property of the internal `$$state` object.
Object.defineProperty(proto, '$$state', {
enumerable: true,
set: function(val) {
val.stack = new Error().stack;
this._$$state = val;
},
get: function() {
return this._$$state;
}
});
return $delegate;
}]);
然后在 angular 代码中搜索消息 "possibly unhandled rejection" 并在该行放置一个断点。当到达断点时,在控制台打印出toCheck.stack
的值,你会看到这样的东西:
>> toCheck.stack
"set@http://localhost:8000/js/dual-site.js:18:19
Promise@http://localhost:8000/js/angular.js:17008:22
then@http://localhost:8000/js/angular.js:17016:20
catch@http://localhost:8000/js/angular.js:17026:14
SyncStrategy.prototype.send@http://localhost:8000/js/angular-state-machine.js:436:24
StateMachine/this.send@http://localhost:8000/js/angular-state-machine.js:235:16
违规代码是调用 angular 的 catch/then 函数的框架。
我有一个代码 AngularJS:
service.doSomething()
.then(function(result) {
//do something with the result
});
在 AngularJS 1.5.9 中,当我在 .then()
部分出现错误时,例如:
service.doSomething()
.then(function(result) {
var x = null;
var y = x.y;
//do something with the result
});
我收到了明确的错误消息:
TypeError: Cannot read property 'y' of null
但是在使用相同代码的 1.6 版本中,我遇到了不同的错误:
Possibly unhandled rejection: {} undefined
我知道这个跟this change有关,解决方案很简单,加.catch()
块:
service.doSomething()
.then(function(result) {
var x = null;
var y = x.y;
//do something with the result
})
.catch(console.error);
现在我又得到了我想要的东西:
TypeError: Cannot read property 'y' of null
但是如何在不在每个地方添加 .catch()
块的情况下为整个应用程序获得相同的结果(更详细的错误)?
我测试了建议的解决方案,通过添加以下内容来禁用此功能:
$qProvider.errorOnUnhandledRejections(false);
但情况更糟 - 我在控制台中没有任何东西!错误被吞没在某个地方,根本没有记录。我不确定 AngularJS 1.6 或我的配置是否有问题。
您是否知道如何 "restore" 从版本 1.5.9 开始记录行为?
编辑:
添加自定义错误处理程序:
.factory('$exceptionHandler', function($log) {
return function(exception, cause) {
$log.warn(exception, cause);
};
})
一点帮助也没有。在错误处理程序中,我已经收到 "wrapped" 错误。
此问题已通过 fix($q): Add traceback to unhandled promise rejections -- Commit 316f60f and the fix is included in the v1.6.1 release 解决。
即使在我的 httpErrorInterceptor 中使用版本 1.6.1 我也有问题,对于一个用例,如果我的 api return 404 我必须尝试使用其他数据的另一个请求......所以在在这种情况下,我只拒绝请求并且 angular 抛出未处理的拒绝错误...
我安装了 1.5.9,现在没有错误了!
我通过将 angular-ui-router 升级到 0.3.2 解决了版本 1.6.1 中的相同问题。
还有另一种情况,将 finally()
处理程序添加到 promise 会产生错误:
http://plnkr.co/edit/eT834BkIEooAMvrVcLDe
因为 finally()
创建了一个新的承诺并在其上调用了解析器。 (在拒绝案例中拒绝第二个)
我已经在 plnkr 中进行了修复,但看起来不太好。
当 angular-ui-router (ui-sref) 使用 angular ver1.6.1 未处理被拒绝的承诺时,我遇到了相同的未处理拒绝错误 & 默认情况下启用此功能。
对于任何想要解决方法的人(尽管不推荐),您可以像这样在全局范围内阻止未处理的承诺拒绝 —
app.config(['$qProvider', function ($qProvider) {
$qProvider.errorOnUnhandledRejections(false);
}]);
errorOnUnhandledRejections(假);对我来说不是解决方案。
您确实需要定义异常处理程序...但是...将其包装在超时函数中:这将强制抛出原始 exception/stack 跟踪。
要使错误在 Web 控制台中显示为错误,如您最初预期的那样:
ng.factory('$exceptionHandler', function($log) {
return function(exception, cause) {
// do some some stuff...
setTimeout(function(){
// throw the original exception (with correct line #'s etc)
throw exception;
})
};
});
这里是超时技巧: Why can I not throw inside a Promise.catch handler?
我通过在 catch 块中添加默认值解决了这个错误,例如:
service.doSomething()
.then(function(response) {
var x = null;
var y = x.y;
}).catch(function(error) {
var y = 0;
});
(考虑到我不是经验丰富的 angular 开发人员)
第一个选项只是按照建议 Cengkuru Michael:
在 $qProvider 配置中使用 disablinconfiguringerrorOnUnhandledRejections
隐藏错误
app.config(['$qProvider', function ($qProvider) {
$qProvider.errorOnUnhandledRejections(false);
}]);
BUT 这只会关闭日志记录。错误本身将保持
在这种情况下,更好的解决方案 将是 - 使用 .catch()
方法处理拒绝:
service.doSomething()
.then(function (response) {})
.catch(function (err) {});
有用的链接:
此信息帮助我追踪(在我的例子中)创建承诺而不是添加错误处理程序的内容。我发现它隐藏在问题 #2889 "Possibly unhandled rejection with Angular 1.5.9".
的讨论中要点是,补丁 $q
缓存创建承诺时的堆栈跟踪,以便在触发错误时可以检索它。
为此,请插入此代码以装饰 $q
靠近 angular 应用顶部的某个位置:
// Decorate the $q service when app starts
app.decorator('$q', ["$delegate", function($delegate) {
// Create a new promise object
var promise = $delegate.when();
// Access the `Promise` prototype (nonstandard, but works in Chrome)
var proto = promise.__proto__;
// Define a setter for `$$state` that creates a stacktrace
// (string) and assigns it as a property of the internal `$$state` object.
Object.defineProperty(proto, '$$state', {
enumerable: true,
set: function(val) {
val.stack = new Error().stack;
this._$$state = val;
},
get: function() {
return this._$$state;
}
});
return $delegate;
}]);
然后在 angular 代码中搜索消息 "possibly unhandled rejection" 并在该行放置一个断点。当到达断点时,在控制台打印出toCheck.stack
的值,你会看到这样的东西:
>> toCheck.stack
"set@http://localhost:8000/js/dual-site.js:18:19
Promise@http://localhost:8000/js/angular.js:17008:22
then@http://localhost:8000/js/angular.js:17016:20
catch@http://localhost:8000/js/angular.js:17026:14
SyncStrategy.prototype.send@http://localhost:8000/js/angular-state-machine.js:436:24
StateMachine/this.send@http://localhost:8000/js/angular-state-machine.js:235:16
违规代码是调用 angular 的 catch/then 函数的框架。