I am using the AngularJS implementation of $q.
Given the following functions:
doTask1: function ($scope) {
var defer = $q.defer();
$http.get('/abc')
.success(function (data) {
defer.resolve();
})
.error(function () {
defer.reject();
});
return defer.promise;
},
doTask2: function ($scope) {
var defer = $q.defer();
var x = 99;
return defer.promise;
},
I know I can delay execution of another function like this:
os.doTask1()
.then(function () {
doTask3();
});
I would like to start off doTask1 and doTask2 at the same time. Is there a way I can do this and still delay execution so that doTask3() will not execute until doTask1 and doTask2 have ended with success.
$q.all
is what you're looking for. ( Documentation )
$q.all
takes multiple promises, either in an array or object, and returns a brand new promise that will be resolve when all the passed-in promises are resolved. If you passed in an array of promises, the new promise is resolved with an array of values which correspond to the promises:
$q.all([doTask1(), doTask2()]).then(function(results) {
// results[0] == result of doTask1
// results[1] == result of doTask2
doTask3();
});
If you passed in an object of key-promise pairs, it will be resolved with an object with keys that match the object you passed in, each value nicely corresponding to the value of that key's resolved promise:
$q.all({one: doTask1(), two: doTask2()}).then(function(results) {
// results.one == result of doTask1
// results.two == result of doTask1
doTask3();
});
Because of promise chaining (eg, when you return a promise from a then
function, it creates a new promise that resolves to the resolved value of the promise you returned), you can do some cool stuff:
var bothPromises = $q.all([doTask1(), doTask2()]);
var task3Promise = bothPromises.then(function(results) {
var result1 = results[0];
var result2 = results[1];
return doTask3(result1, result2);
});
task3Promise.then(function(resultOfDoTask3) { ... });
It is worth nothing that if any of the promises passed to $q.all
is rejected, the promise that is returned will also be rejected. See the Angular $q
documentation for more information.
This is (barely) tangential to the question, but I think it's a neat trick: if you happen to use CoffeeScript, you can use destructuring to get to the promises' resolved values.
For arrays:
$q.all([doTask1(), doTask2()]).then ([result1, result2]) ->
# ...
And for objects
$q.all(one: doTask1(), two: doTask2()).then ({one, two}) ->
# note that you have to use the same key names
# as in the object you passed to `$q.all`
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.