Pour essayer de trouver quelque chose qui fonctionne exactement comme async.eachSeries, j’ai besoin d’une liste d’actions asynchrones exécutées dans l’ordre (mais pas en parallèle), mais je ne trouve pas le moyen de le faire dans l’ES6 natif. S'il vous plaît?
p.s. Je pensais aux générateurs/rendement, mais je n’ai pas encore acquis l’expérience.
Modifier 1
par demande, voici un exemple:
Supposons ce code:
let model1 = new MongooseModel({prop1: "a", prop2: "b"});
let model2 = new MongooseModel({prop1: "c", prop2: "d"});
let arr = [model1 , model2];
Maintenant, je veux le parcourir en série, pas en parallèle, donc avec le NPM "async", c'est facile:
async.eachSeries(arr, (model, next)=>{
model.save.then(next).catch(next);
}, err=>{
if(err) return reject(error);
resolve();
})
Ma question est la suivante: avec ES6, puis-je le faire en mode natif? sans le package 'async' du NPM?
Modifier 2
Avec async/wait, cela peut être fait facilement:
let model1 = new MongooseModel({prop1: "a", prop2: "b"});
let model2 = new MongooseModel({prop1: "c", prop2: "d"});
let arr = [model1 , model2];
for(let model of arr){
await model.save();
}
Pour ceux qui aiment les réponses courtes:
[func1, func2].reduce((p, f) => p.then(f), Promise.resolve());
Supposons que vous souhaitiez appeler une fonction asynchrone sur un tableau de données et que vous souhaitez qu’elles soient appelées de manière séquentielle, et non en parallèle.
L'interface pour async.eachSeries()
est comme ceci:
eachSeries(arr, iterator, [callback])
Voici comment simuler cela avec des promesses:
// define helper function that works kind of like async.eachSeries
function eachSeries(arr, iteratorFn) {
return arr.reduce(function(p, item) {
return p.then(function() {
return iteratorFn(item);
});
}, Promise.resolve());
}
Cela suppose que iteratorFn
prend l'élément à traiter en tant qu'argument et qu'il renvoie une promesse.
Voici un exemple d'utilisation (supposant que vous avez une fs.readFileAsync()
promisifiée) et une fonction appelée speak()
qui renvoie une promesse lorsque vous avez terminé:
var files = ["hello.dat", "goodbye.dat", "genericgreeting.dat"];
eachSeries(files, function(file) {
return fs.readFileAsync(file).then(function(data) {
return speak(data);
});
});
Cela permet à l'infrastructure de promesse de tout séquencer pour vous.
Il est également possible pour vous de séquencer les choses manuellement (bien que je ne sois pas pourquoi):
function eachSeries(arr, iteratorFn) {
return new Promise(resolve, reject) {
var index = 0;
function next() {
if (index < arr.length) {
try {
iteratorFn(arr[index++]).then(next, reject);
} catch(e) {
reject(e);
}
} else {
resolve();
}
}
// kick off first iteration
next();
});
}
Ou, une version plus simple qui enchaîne manuellement les promesses:
function eachSeries(arr, iteratorFn) {
var index = 0;
function next() {
if (index < arr.length) {
return iteratorFn(arr[index++]).then(next);
}
}
return Promise.resolve().then(next);
}
Notez que l’une des versions manuelles doit entourer iteratorFn()
avec try/catch
afin de s’assurer qu’elle est à la portée de la main (conversion des exceptions en rejet). .then()
est automatiquement protégé afin que les autres schémas ne soient pas obligés de capturer manuellement les exceptions, car .then()
les capture déjà pour vous.
En tant qu'extension de la réponse fournie par @jib ..., vous pouvez également associer un tableau d'éléments à des fonctions asynchrones, comme suit:
[item1, item2]
.map(item => async (prev_result) => await something_async(item))
.reduce((p, f) => p.then(f), Promise.resolve())
.then(() => console.log('all done'));
Notez que prev_result
sera la valeur renvoyée par la précédente évaluation de something_async
, ce qui correspond à peu près à un hybride entre async.eachSeries
et async.waterfall
.
// Téléchargement de ceci pour les systèmes qui exécutent une version inférieure de nodejs (Azure: /) Pas le plus court mais le plus beau que je puisse imaginer
par exemple, disons "functionWithPromise" renvoie une promesse et attend un élément.
functionWithPromise(item);
promisesArray =[];
//syncornized
itemsArray.forEach(function (item){
promisesArray.Push(functionWithPromise(item));
});
Promise.all(promisesArray).then(function (values){
//profit
});
Vous pouvez chaîner en retournant le callback then
. Par exemple:
new Promise(function(resolve, reject){
resolve(1)
}).then(function(v){
console.log(v);
return v + 1;
}).then(function(v){
console.log(v)
});
Imprimera:
1
2
Cela fonctionne bien entendu lors de la résolution asynchrone des promesses:
new Promise(function(resolve, reject){
setTimeout(function(){
resolve(1);
}, 1000)
}).then(function(result){
return new Promise(function(resolve, reject){
setTimeout(function(){
console.log(result);
resolve(result + 1);
}, 1000)
});
}).then(function(results){
console.log(results);
});
Impression:
1
2