-
Notifications
You must be signed in to change notification settings - Fork 27.5k
fix($q): promises should still resolve outside of the $digest/$apply phase #3539
Conversation
…phase Add $rootScope.$apply() call upon resolve/reject if outside a digest phase Closes angular#2431
Thanks for the PR!
If you need to make changes to your pull request, you can update the commit with Thanks again for your help! |
CLA is recently signed. Not sure what I did wrong on my commit message (I installed the hook)! |
var deferreds = {}; | ||
|
||
var $q = qFactory(function(callback){ | ||
$rootScope.$evalAsync(callback); | ||
},$exceptionHandler); |
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.
$timeout still needs the old nextTick implementation for ngAnimate/etc unit tests to pass.
I am not sure that my hack of $timeout is the appropriate one. Perhaps the promise API should be extended to include another function skipApply()
that will suppress the $apply call upon promise resolution/rejection. i.e.:
var defer = $q.defer().skipApply();
// and/or
var promise = somePromiseReturningFunc();
promise.then(onResolve,onErr).skipApply();
even in the skipApply
case I would think continuation of the promise chain should not wait for a $digest cycle, but simply prevent dirty checking of the scope.
Thanks for PR. We are aware of this issue, but I think your solution will cause too much breakage and timing issues. The $timeout hack is just a manifestation of this. Also with your change, you have to use $browser in your tests, which is one of the apis that is currently not even documented as public api and our goal is to completely get rid of it for many other reasons. |
I am not so sure it would introduce new timing issues, except those that are desired. Currently it has the same behavior as the old implementation unless the current
|
As for the |
This change causes a new $digest to be scheduled in the next tick if a task was was sent to the $evalAsync queue from outside of a $digest or an $apply. While this mode of operation is not common for most of the user code, this change means that $q promises that utilze $evalAsync queue to guarantee asynchronicity of promise apis will now also resolve outside of a $digest, which turned out to be a big pain point for some developers. The implementation ensures that we don't do more work than needed and that we coalese as much work as possible into a single $digest. The use of $browser instead of setTimeout ensures that we can mock out and control the scheduling of "auto-flush", which should in theory allow all of the existing code and tests to work without negative side-effects. Closes angular#3539 Closes angular#2438
please take a look at the commit above (which I threw into PR #3699) |
closing this one in favor of #3699 |
This change causes a new $digest to be scheduled in the next tick if a task was was sent to the $evalAsync queue from outside of a $digest or an $apply. While this mode of operation is not common for most of the user code, this change means that $q promises that utilze $evalAsync queue to guarantee asynchronicity of promise apis will now also resolve outside of a $digest, which turned out to be a big pain point for some developers. The implementation ensures that we don't do more work than needed and that we coalese as much work as possible into a single $digest. The use of $browser instead of setTimeout ensures that we can mock out and control the scheduling of "auto-flush", which should in theory allow all of the existing code and tests to work without negative side-effects. Closes angular#3539 Closes angular#2438
This change causes a new $digest to be scheduled in the next tick if a task was was sent to the $evalAsync queue from outside of a $digest or an $apply. While this mode of operation is not common for most of the user code, this change means that $q promises that utilze $evalAsync queue to guarantee asynchronicity of promise apis will now also resolve outside of a $digest, which turned out to be a big pain point for some developers. The implementation ensures that we don't do more work than needed and that we coalese as much work as possible into a single $digest. The use of $browser instead of setTimeout ensures that we can mock out and control the scheduling of "auto-flush", which should in theory allow all of the existing code and tests to work without negative side-effects. Closes #3539 Closes #2438
This change causes a new $digest to be scheduled in the next tick if a task was was sent to the $evalAsync queue from outside of a $digest or an $apply. While this mode of operation is not common for most of the user code, this change means that $q promises that utilze $evalAsync queue to guarantee asynchronicity of promise apis will now also resolve outside of a $digest, which turned out to be a big pain point for some developers. The implementation ensures that we don't do more work than needed and that we coalese as much work as possible into a single $digest. The use of $browser instead of setTimeout ensures that we can mock out and control the scheduling of "auto-flush", which should in theory allow all of the existing code and tests to work without negative side-effects. Closes angular#3539 Closes angular#2438
This change causes a new $digest to be scheduled in the next tick if a task was was sent to the $evalAsync queue from outside of a $digest or an $apply. While this mode of operation is not common for most of the user code, this change means that $q promises that utilze $evalAsync queue to guarantee asynchronicity of promise apis will now also resolve outside of a $digest, which turned out to be a big pain point for some developers. The implementation ensures that we don't do more work than needed and that we coalese as much work as possible into a single $digest. The use of $browser instead of setTimeout ensures that we can mock out and control the scheduling of "auto-flush", which should in theory allow all of the existing code and tests to work without negative side-effects. Closes angular#3539 Closes angular#2438
A number of issues have been raised (see #2431) because the current promise implementation has the unexpected behavior of not forwarding execution to the
onResolve
oronReject
callbacks until the next $digest cycle, nor does it schedule a new cycle.The currently recommended solution is to wrap all callbacks with $apply, but that is unnecessarily cumbersome (the user will almost always wants $apply called). It becomes increasingly problematic when dealing with longer promise chains, or using third party libraries that expect conventional promises as input.
Closes #2431