Reputation: 171489
I started from a demo Ionic app (ionic start myApp sidemenu
), and added a resolve
to one of the views:
resolve: {
issue: function($q, $timeout) {
var defer = $q.defer();
//defer.reject(); // Doesn't work browser or device
$timeout(defer.reject); // Works in browser, but not device
return defer.promise;
}
}
I monitor rejected resolve
s here:
.run(function($ionicPlatform, $rootScope, $ionicLoading) {
$ionicPlatform.ready(function() {
// regular stuff here
$rootScope.$on('$stateChangeError', function() {
$ionicLoading.show({
template: 'All good!'
});
});
});
});
For some reason, if resolve
rejects immediately (see defer.reject()
above), the callback of $stateChangeError
is not run. If I do exactly the same, but outside of Ionic, it works!
Moreover, trying to delay the resolve
rejection by doing $timeout(defer.reject);
results in a different behaviour. Now it works in a browser as expected, but still doesn't work on a device. Trying to delay even more, results in success on device:
$timeout(function() {
defer.reject();
}, 250); // Doesn't work for me with 200 or less
Can anyone shed light on this?
SEE HERE HOW TO REPRODUCE THE ISSUE
Upvotes: 1
Views: 1834
Reputation: 6711
From my experience with Angular and the promise model. In order to resolve/reject a promise Angular must tick over one cycle of the JS event loop - nextTick - and this can be accomplished using $scope.apply() which is how we mock such things in unit tests.
This is an awesome article that talks about $timeout and $scope.$evalAsync - from what I can gather $timeout is evaluating the function in the next tick. Which is the reason that this code works the way you outlined.
resolve: {
issue: function($q, $timeout) {
var defer = $q.defer();
//defer.reject(); // <---- no nextTick
$timeout(defer.reject); // <---- $timeout evaluates on nextTick
return defer.promise;
}
}
This is another article that talks about the textTick implementation of $q.
I know that this doesnt solve your problem - but it should shed some light onto why this is happening! Good luck!
Upvotes: 1
Reputation: 9616
1) $timeout needs to be more than 200
First off - I have never seen constructs like $timeout(deferred.reject); I don't believe defered.reject returns any function that $timeout expects.
I tried 50 and it works. Here is http://plnkr.co/edit/6NXZEXrfz3WHVqoaRYJB?p=preview with timeout 50 or less but works i.e. All Good! is printed.
resolve: {
test: function($q, $timeout) {
var defer = $q.defer();
$timeout(function(){
defer.reject();
},50);
return defer.promise;
}
}
This is with stateChangeError outside the iconicPlatform.ready
2) $stateChangeError not working
I am thinking that this has to do with the timings. I don;t know the internals as to when the ionicPlatform.ready() gets executed but I am not sure if it is even necessary. Your starter
module depends on it so it will be loaded. Sometimes seed projects have more than 'seed'.
UPDATED - Found a bug with respect to ready() on other devices. It seems that ready method is not getting executed.
https://github.com/driftyco/ionic/issues/1751
Upvotes: 1