在Angular 1.6中可能无法处理拒绝

Pio*_*ski 29 javascript angularjs angular-promise angular-providers angularjs-1.6

我有一个AngularJS代码:

service.doSomething()
  .then(function(result) {
      //do something with the result
  });
Run Code Online (Sandbox Code Playgroud)

在AngularJS 1.5.9中,当我在该.then()部分中有错误时:

service.doSomething()
  .then(function(result) {
      var x = null;
      var y = x.y;
      //do something with the result
  });
Run Code Online (Sandbox Code Playgroud)

我收到明确的错误消息:

TypeError:无法读取null的属性"y"

但是在版本1.6中使用相同的代码我得到了一个不同的错误:

可能是未处理的拒绝:{}未定义

我知道这与此更改有关,通过添加.catch()块,单个解决方案非常简单:

service.doSomething()
  .then(function(result) {
      var x = null;
      var y = x.y;
      //do something with the result
  })
  .catch(console.error);
Run Code Online (Sandbox Code Playgroud)

现在我再次拥有我想要的东西:

TypeError:无法读取null的属性"y"

但是如何在不在.catch()每个地方添加块的情况下为整个应用程序获得相同的结果(更详细的错误)?

我测试了建议的解决方案,通过添加:

$qProvider.errorOnUnhandledRejections(false);
Run Code Online (Sandbox Code Playgroud)

但有了这种情况甚至更糟 - 我在控制台中没有任何东西!错误被某处吞没,根本没有记录.我不确定AngularJS 1.6或我的配置是否有问题.

您是否有任何想法如何从1.5.9版"恢复"日志记录行为?

编辑:

添加定制错误处理程序

.factory('$exceptionHandler', function($log) {
  return function(exception, cause) {
    $log.warn(exception, cause);
  };
})
Run Code Online (Sandbox Code Playgroud)

根本没有帮助.在错误处理程序中,我已经收到"包装"错误.

gka*_*pak 18

这已通过修复($ q)修复:将回溯添加到未处理的承诺拒绝 - 提交316f60f,修复程序包含在v1.6.1版本中.

  • @httpete:OP询问如何获得更明确的错误,而不是如何抑制未处理的拒绝(这不是一个好主意). (6认同)
  • 好吧,我使用的是 1.6.1,但仍然出现错误。即使我确实有错误回调。问题是我的回调需要返回一个被拒绝的承诺,以便客户端知道服务有错误。然后噗!$http(config).then( (response) => {...}, (error) => { return $q.reject(error); } ); (2认同)

And*_*kyi 15

第一个选项只是隐藏errorOnUnhandledRejections在$ qProvider配置中的disablinconfiguration错误,如同Cengkuru Michael建议:

app.config(['$qProvider', function ($qProvider) {
    $qProvider.errorOnUnhandledRejections(false);
}]);
Run Code Online (Sandbox Code Playgroud)

这样只会关闭日志记录.错误本身将保留

在这种情况下,更好的解决方案是 - 使用.catch()方法处理拒绝:

service.doSomething()
    .then(function (response) {})
    .catch(function (err) {});
Run Code Online (Sandbox Code Playgroud)

有用的链接:


小智 8

我通过将angular-ui-router升级到0.3.2来修复版本1.6.1的相同问题.


wu-*_*lee 5

这些信息有助于我追踪(在我的情况下)创建承诺而不添加错误处理程序的原因。我发现它被埋在对问题#2889“ Angular 1.5.9可能未处理的拒绝”的讨论中。

要点是修补程序,$q以在创建promise时缓存堆栈跟踪,以便在触发错误时可以对其进行检索。

为此,请插入以下代码以装饰$q您的角度应用顶部附近的地方:

// 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;
}]);
Run Code Online (Sandbox Code Playgroud)

然后在角度代码中搜索消息“可能未处理的拒绝”,并在该行上放置一个断点。当达到断点时,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
Run Code Online (Sandbox Code Playgroud)

令人反感的代码是调用angular的catch / then函数的帧。

  • 这应该是正确的答案,这应该是 Angular 的一部分。非常感谢!! (2认同)