Nowadays I am playing with $q
of super heroic AngularJS. I have three asynchronous
task. Let's call them taskA
, taskB
and taskC
. I want to execute them one by one. Currently I am using $q
's all()
method. I am doing following:
var taskA = function() {
var d = $q.defer();
$timeout(function() {
$log.log('Task A');
d.resolve('A is done');
}, Math.random() * 5000);
return d.promise;
};
var taskB = function() {
var d = $q.defer();
$timeout(function() {
$log.log('Task B');
// d.resolve('B is done');
d.reject('B is rejected');
}, Math.random() * 5000);
return d.promise;
};
var taskC = function() {
var d = $q.defer();
$timeout(function() {
$log.log('Task C');
//d.resolve('C is done');
d.reject('C is rejected');
}, Math.random() * 5000);
return d.promise;
};
$scope.startWithAll = function() {
$log.log('With all started');
var promises = [taskA(), taskB(), taskC()];
$q.all(promises).then(
//success callback...
function(result) {
$log.log(result);
},
//error callback
function(error) {
$log.log(error);
},
//progress callback
function() {
//todo implement it
}
).finally(function() {
$log.log('I am from finally');
});
};
The problem with this approach is that all my tasks are executed in parallel. And in success
of then
I get the result of each task in an array
. If any of the task is rejected then rest of the tasks continue the execution but the error callback
is executed and I get the error object
in the callback. What I want to do is that at first only taskA
should be executed then taskB
and then taskC
if any of them is rejected or failed then rest of the task should not be executed. And there execution should not be parallel it should be serial. To to execute them serially I am doing this :
$scope.startSerial = function() {
$log.log('Serially started');
$q.when().then(function(result) {
$log.log(result);
return taskA();
}).then(function(result) {
$log.log(result);
return taskB();
}).then(function(result) {
$log.log(result);
return taskC();
}).finally(function() {
$log.log('I am from finally');
});
};
So this solves my problem. But the thing is that in first callback
I am getting undefined
, I don't have any problem with that so we can omit this part. But currently I have only three tasks so this approach is fine but what if tomorrow I have more than three task then this will not be a good way to implement. Is there any other way to do so cause I can not keep on adding multiple then
just below another. I have created the plunkr for this . What I am thinking is about creating a service
which will create this task execution hierarchy but I don't know how to do this.
You can create a loop, that connects all your promises:
function each(arr, func) {
for (var i = 0; i < arr.length; i++) {
func(arr[i], i);
}
}
$scope.startSerial = function() {
var funcs = [taskA, taskB, taskC];
$log.log('Serially started');
var s = $q.when();
each(funcs, function (func) {
s = s.then(function (result) {
$log.log(result);
return func();
});
});
s.finally(function () {
$log.log('I am from finally');
});
}
This should result in the same behavior as your original script, but you can simply adjust the array funcs
instead of adding additional blocks of code for each promise.