I'm trying to understand the promise API and chaining, particularly the timing when $timeout
is used with .then()
. What I had expected from the following is that since $timeout
returns a promise, .then()
would not be called until it had resolved.
But instead of ABAB, it's ABBA all the time.
How can I use the promise API to ensure that a long-running call (or delayed call using $timeout
) is actually complete before the .then()
gets executed?
Code
angular
.module('app', [])
.controller('ThenCtrl', ThenCtrl);
function ThenCtrl($timeout, $q) {
var vm = this;
vm.items = [];
$q.when(pushA()).then(pushB());
$timeout(pushA, 5000).then(pushB());
function pushA() {
vm.items.push('A');
}
function pushB() {
vm.items.push('B');
}
}
Markup
<div ng-app="app">
<div ng-controller="ThenCtrl as vm">
{{vm.items}}
</div>
</div>
I've set up a fiddle: https://jsfiddle.net/kan3c61t/
Don't invoke the functions inside the .then
methods.
̶$̶q̶.̶w̶h̶e̶n̶(̶p̶u̶s̶h̶A̶(̶)̶)̶.̶t̶h̶e̶n̶(̶p̶u̶s̶h̶B̶(̶)̶)̶;̶
$q.when(pushA()).then(pushB);
̶$̶t̶i̶m̶e̶o̶u̶t̶(̶p̶u̶s̶h̶A̶,̶ ̶5̶0̶0̶0̶)̶.̶t̶h̶e̶n̶(̶p̶u̶s̶h̶B̶(̶)̶)̶;̶
$timeout(pushA, 5000).then(pushB);
Instead pass the functions as arguments to the .then
method. The $q
service will hold those functions to be invoked later.
The way the $q
service works is it stores the argument of the .then
method as a function to be invoked later. In this case, the $q
service was storing the value returned by pushB()
with the side effect of pushing B
immediately onto the array.
The DEMO on JSFiddle