Possibly raw deviation in Angular 1.6

I have code with AngularJS:

service.doSomething() .then(function(result) { //do something with the result }); 

In AngularJS 1.5.9, when I have an error in the .then() section, for example:

 service.doSomething() .then(function(result) { var x = null; var y = xy; //do something with the result }); 

I get an error message:

TypeError: Unable to read property 'y' null

But in version 1.6 with the same code, I get another error:

Possible raw rejection: {} undefined

I know that this is due to this change , and one solution is quite simple by adding a .catch() block:

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

Now I again have what I want:

TypeError: Unable to read property 'y' null

But how to get the same result (a more detailed error) for the entire application without adding the .catch() block in every place?

I tested the proposed solution to disable it by adding:

 $qProvider.errorOnUnhandledRejections(false); 

But with this the situation is even worse - I have NO ANYONE in the console! The error is swallowed somewhere and is not recorded at all. I'm not sure if this is a problem with AngularJS 1.6 or with my configuration.

Do you have any ideas on how to "restore" log behavior from version 1.5.9?

EDIT:

Adding a custom error handler:

 .factory('$exceptionHandler', function($log) { return function(exception, cause) { $log.warn(exception, cause); }; }) 

doesn't help at all. In the error handler, I already got a wrapped error.

+17
javascript angularjs angular-promise angular-providers
Dec 22 '16 at 10:56
source share
9 answers

This is fixed using 316f60f , and the fix is ​​included in v1.6.1 release .

+16
Dec 22 '16 at 12:28
source share

I fixed the same problem with version 1.6.1 by updating angular -ui-router to 0.3.2.

+7
Jan 9 '17 at 11:29 on
source share

The first option is to simply hide the error with disablinconfiguring errorOnUnhandledRejections in $ qProvider configuratio, as suggested by Cengkuru Michael :

 app.config(['$qProvider', function ($qProvider) { $qProvider.errorOnUnhandledRejections(false); }]); 

BUT , this will disable registration. The error itself will remain

The best solution in this case would be: handling the deviation using the .catch() method:

 service.doSomething() .then(function (response) {}) .catch(function (err) {}); 

Useful links:

+6
Jul 28 '17 at 8:28
source share

I got the same unhandled rejection error when a rejected promise is not handled by angular -ui-router (ui-sref) using angular ver1.6.1, and this function is enabled by default.

For those who want a workaround (not recommended), you can globally disable raw promises such as:

app.config(['$qProvider', function ($qProvider) { $qProvider.errorOnUnhandledRejections(false); }]);

+3
Jan 18 '17 at 6:20
source share

There is another case by adding a finally() handler to the promise that generates the error: http://plnkr.co/edit/eT834BkIEooAMvrVcLDe

Because finally() creates a new promise and calls the converter on it. (Deviation of the second in case of deviation)

I installed the fix in plnkr, but it doesn’t look very good.

+2
Jan 13 '17 at 16:11
source share

This information helped me track what (in my case) created a promise and did not add an error handler. I found him buried in a discussion of question # 2889 "Perhaps an unhandled deviation with Angular 1.5.9 . "

The bottom line is the $q patch to cache the stack trace when creating promises so that it can be obtained when an error is triggered.

To do this, paste this code to decorate $q somewhere at the top of your Angular application:

 // 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; }]); 

Then find the Angular code for the message “possibly unhandled rejection” and place a breakpoint on this line. When the breakpoint is reached, print the value of toCheck.stack on the console and you will see something like this:

 >> 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 

Abusive code is a frame that calls Angular's catch / then function.

+2
18 Oct '17 at 16:59 on
source share

I have a problem even with version 1.6.1 in my httpErrorInterceptor, for one usecase my, if my api return 404 I need to try another request with different data ... so in this case I reject the request and angular throw an unhandled reject error ...

I install 1.5.9 and now there are no more errors!

0
Jan 05 '17 at 8:58
source share

errorOnUnhandledRejections (false); for me there was no solution.

You really need to define an exception handler ... however ... wrap it in a timeout function: this will cause the original exception / stack trace to be thrown.

So that the error message appears as an error in the web console, as you originally planned:

 ng.factory('$exceptionHandler', function($log) { return function(exception, cause) { // do some some stuff... setTimeout(function(){ // throw the original exception (with correct line # etc) throw exception; }) }; }); 

Here is the timeout trick: Why can't I throw inside the Promise.catch handler?

0
May 10 '17 at 10:02 PM
source share

I solved this error by adding a default value to the catch block, for example:

 service.doSomething() .then(function(response) { var x = null; var y = xy; }).catch(function(error) { var y = 0; }); 

(note that I'm not an experienced angular developer)

0
Jul 16 '17 at 14:49
source share



All Articles