-
Notifications
You must be signed in to change notification settings - Fork 27.5k
feat($q): report promises with non rejection callback #13662
Conversation
8c2419d
to
e6c1449
Compare
@@ -702,12 +702,13 @@ angular.module('ngResource', ['ng']). | |||
return $q.reject(response); | |||
}); | |||
|
|||
promise.finally(function() { | |||
promise = promise.finally(function(response) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The .finally
callback doesn't take any arguments and the result is ignored unless it's a promise (and even when it's a promise the result of that promise is ignored). I think this arg and the return can be dropped.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fact: If a resource
call is canceled the internal promise is rejected
The previous code did the following:
internalPromise.finally(...)
this creates a promise that I will call X
internalPromise.then(...)
this second promise is returned. I will call this promise Y
If internalPromise
is rejected, then it will reject X
and Y
. The user can handle the rejection of Y
as this is what they receive, but they can do nothing about X
. This leaves us with 2 options
1/ Change the code to
promise.finally(...).then(noop, noop);
promise = promise.then(...);
This will handle any rejections from X
2/ What is in this patch
promise = promise.finally(...).then(...);
The second option has the benefit of not creating another promise
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That all makes sense... but response
is undefined 100% of the time because the .finally
callback doesn't take any arguments. You can drop the response
arg and return statement...
@gkalpak added an option to disable this behavior. PTAL. |
* @kind function | ||
* | ||
* @description | ||
* Retrieves or overrides on wheter to generate an error when a rejected promise is not handled. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
on wheter --> whether (?)
I left some comments. Some additional thoughts:
|
e812b71
to
d18ff2e
Compare
Updated the PR with the changes. Made the change to That said, I do not think that there is a need to add any special documentation for this case. |
a85c87f
to
f03988c
Compare
|
||
/** | ||
* @ngdoc method | ||
* @name $qProvider#errorOnUnhandledRejections |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder where this method shows up in the docs (considering there are no docs for $qProvider
).
I think there should "standalone" docs for $qProvider
(even if just containing this method), but it can be tackled in a follow-up PR.
I left a couple of minor comments, but it LGTM otherwise. I'm not sure about the default value of the flag. I guess |
Added a page for |
About backporting this to 1.5. I am fine as long as the default value is |
Rejected promises that do not have a callback to handle the rejection report this to $exceptionHandler so they can be logged to the console. BREAKING CHANGE Unhandled rejected promises will be logged to $exceptionHandler. Tests that depend on specific order or number of messages in $exceptionHandler will need to handle rejected promises report. Closes: angular#13653 Closes: angular#7992
Angular 1.5 has a bug that causes angular's `$exceptionHandler` to be called for rejected `$q` promises even if they have a rejection handler. This bug caused duplicate error messages in Etcher. A consequence of upgrading to Angular 1.6 is that `$q` promises without a rejection handler will throw `Possibly unhandled rejection` errors. To avoid these errors, this commit moves code responsible for opening a tooltip from the template to the controller and handles the rejection. Other packages upgraded: - angular-moment to v1.0.1 - angular-ui-router to v0.4.2 - angular-mocks to v1.6.1 Change-type: patch Changelog-Entry: Fix duplicate error messages Fixes: #1082 See: angular/angular.js#7992 See: angular/angular.js#13662
Angular 1.5 has a bug that causes angular's `$exceptionHandler` to be called for rejected `$q` promises even if they have a rejection handler. This bug caused duplicate error messages in Etcher. A consequence of upgrading to Angular 1.6 is that `$q` promises without a rejection handler will throw `Possibly unhandled rejection` errors. To avoid these errors, this commit moves code responsible for opening a tooltip from the template to the controller and handles the rejection. Other packages upgraded: - angular-moment to v1.0.1 - angular-ui-router to v0.4.2 - angular-mocks to v1.6.1 Change-type: patch Changelog-Entry: Fix duplicate error messages Fixes: #1082 See: angular/angular.js#7992 See: angular/angular.js#13662
Angular 1.5 has a bug that causes angular's `$exceptionHandler` to be called for rejected `$q` promises even if they have a rejection handler. This bug caused duplicate error messages in Etcher. A consequence of upgrading to Angular 1.6 is that `$q` promises without a rejection handler will throw `Possibly unhandled rejection` errors. To avoid these errors, this commit moves code responsible for opening a tooltip from the template to the controller and handles the rejection. Other packages upgraded: - angular-moment to v1.0.1 - angular-ui-router to v0.4.2 - angular-mocks to v1.6.1 Change-type: patch Changelog-Entry: Fix duplicate error messages Fixes: #1082 See: angular/angular.js#7992 See: angular/angular.js#13662
if (!toCheck.pur) { | ||
toCheck.pur = true; | ||
var errorMessage = 'Possibly unhandled rejection: ' + toDebugString(toCheck.value); | ||
exceptionHandler(errorMessage); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of curiosity, why errorMessage
isn't wrapped by new Error()
so that stack trace is available?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@amalitsky This code path is only used if the value thrown in a promise callback was not an error. We could construct an error object here but it wouldn't be of much value as its stack would end up here and not in the place from where the error comes.
To be useful, only errors need to be thrown in promise callbacks and not other values. Which is a good idea in general.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mgol, wouldn't path also have a reference to the promise invocation?
Rejected promises that do not have a callback to handle the rejection report this to $exceptionHandler so they can be logged to the console.
BREAKING CHANGE
Tests that depend on specific order or number of messages in $exceptionHandler
will need to handle rejected promises report.
Closes: #13653
Closes: #7992