Dans la bibliothèque de promessesQ, vous pouvez effectuer les opérations suivantes pour enchaîner les promesses:
var items = ['one', 'two', 'three'];
var chain = Q();
items.forEach(function (el) {
chain = chain.then(foo(el));
});
return chain;
cependant, ce qui suit ne fonctionne pas avec $ q :
var items = ['one', 'two', 'three'];
var chain = $q();
items.forEach(function (el) {
chain = chain.then(foo(el));
});
return chain;
Utilisez simplement la fonction $ q.when ():
var items = ['one', 'two', 'three'];
var chain = $q.when();
items.forEach(function (el) {
chain = chain.then(foo(el));
});
return chain;
Remarque: foo doit être une usine, par exemple.
function setTimeoutPromise(ms) {
var defer = $q.defer();
setTimeout(defer.resolve, ms);
return defer.promise;
}
function foo(item, ms) {
return function() {
return setTimeoutPromise(ms).then(function () {
console.log(item);
});
};
}
var items = ['one', 'two', 'three'];
var chain = $q.when();
items.forEach(function (el, i) {
chain = chain.then(foo(el, (items.length - i)*1000));
});
return chain;
Redgeoff, votre propre réponse est la façon dont je habitué traduit un tableau en une série de promesses enchaînées.
Le modèle de facto émergent est le suivant:
function doAsyncSeries(arr) {
return arr.reduce(function (promise, item) {
return promise.then(function(result) {
return doSomethingAsync(result, item);
});
}, $q.when(initialValue));
}
//then
var items = ['x', 'y', 'z'];
doAsyncSeries(items).then(...);
Remarques:
.reduce
est un code javascript brut qui ne fait pas partie d'une bibliothèque.result
est le résultat/les données asynchrones précédent et est inclus pour des raisons de complétude. La result
initiale est initialValue
. S'il n'est pas nécessaire de transmettre le résultat, laissez-le simplement de côté.$q.when(initialValue)
en fonction de la promesse que vous utilisez.doSomethingAsync
est foo
(ou ce que foo () renvoie?) - dans tous les cas, une fonction.Si vous êtes comme moi, le motif ressemblera, à première vue, à un refoulement impénétrable, mais une fois que votre œil aura été harmonisé, vous commencerez à le considérer comme un vieil ami.
Modifier
Voici un demo , conçu pour démontrer que le modèle recommandé ci-dessus exécute ses appels doSomethingAsync()
de manière séquentielle, et non immédiatement lors de la construction de la chaîne, comme suggéré dans les commentaires ci-dessous.
Ayant ceci:
let items = ['one', 'two', 'three'];
Une ligne (enfin, 3 pour la lisibilité):
return items
.map(item => foo.bind(null, item))
.reduce($q.when, $q.resolve());
var when = $q.when();
for(var i = 0; i < 10; i++){
(function() {
chain = when.then(function() {
return $http.get('/data');
});
})(i);
}
D'une manière peut-être plus simple que celle de la réponse de redgeoff , si vous n'en avez pas besoin, vous pouvez enchaîner les promesses à l'aide de $q.when()
combiné à .then()
, comme indiqué au début de ce message .
return $q.when()
.then(function(){ return promise1; })
.then(function(){ return promise2; });
Je préfère préparer des fonctions qui renverront des promesses en utilisant angular.bind
(ou Function.prototype.bind
), puis en les liant à une chaîne en utilisant le raccourci-raccourci. Par exemple
// getNumber resolves with given number
var get2 = getNumber.bind(null, 2);
var get3 = getNumber.bind(null, 3);
[get2, get3].reduce(function (chain, fn) {
return chain.then(fn);
}, $q.when())
.then(function (value) {
console.log('chain value =', value);
}).done();
// prints 3 (the last value)
Votre réponse est correcte. Cependant, je pensais fournir une alternative. Vous pourriez être intéressé par $ q.serial si vous vous retrouvez souvent à enchaîner les promesses en série.
var items = ['one', 'two', 'three'];
var tasks = items.map(function (el) {
return function () { foo(el, (items.length - i)*1000)); });
});
$q.serial(tasks);
function setTimeoutPromise(ms) {
var defer = $q.defer();
setTimeout(defer.resolve, ms);
return defer.promise;
}
function foo(item, ms) {
return function() {
return setTimeoutPromise(ms).then(function () {
console.log(item);
});
};
}