weird behavior with already resolved promises inside a digest in 1.4.1 with ngShow and ngAnimate #12143
Description
I have stumbled upon a weird behavior when migrating to angular 1.4.
I'll try to create a plunkr example when/if I have the time later.
For the time being, here's the issue's description.
Here's a simple controller:
var promises = {};
function getElt(eltId) {
var p = promises[eltId];
if (!p) {
promises[eltId] = p = getEltPromise(eltId);
}
return p;
}
function MyCtrl($scope) {
$scope.$digest('eltId', function (eltId) {
this.elt = null;
getElt(eltId)
.then(function (elt) {
this.elt = elt;
})
}
}
The controller watches an id
, and updates an elt
when the id
changes.
The elt
is retrieved using a function that returns a $q promise. elt
is set to null
to indicate the loading state.
The function uses a cache of $q promises, so that it will return the already resolved promise if it is called with an id
it already knows.
When the function returns an already resolved promise, the digest seems to be in a strange state. The template still considers that the elt
is null
, although, when consulting the scope in the console, this.elt
is not null
. Calling $rootScope.$digest()
doesn't change anything.
This also happens when I return a new promise that's resolved when the intiial promise is resolved (next tick since it's already resolved).
function getElt(eltId) {
var p = promises[eltId];
if (!p) {
promises[eltId] = p = getEltPromise(eltId);
}
let d = $q.defer();
p.then(function (chat) {
d.resolve(chat);
});
return d.promise;
}
This issue does not happen if I return a completely new promise, or if I wrap the function call inside a setTimeout.
function getElt(eltId) {
var p = promises[eltId];
if (!p) {
promises[eltId] = p = getEltPromise(eltId);
}
let d = $q.defer();
setTimeout(function () {
p.then(function (chat) {
d.resolve(chat);
});
});
return d.promise;
}