J'utilise caolan's async.js library, plus précisément la méthode .each.
Comment avez-vous accès à l'index dans l'itérateur?
async.each(ary, function(element, callback){
//do stuff here for each element in ary
//how do I get access to the index?
}, function(err) {
//final callback here
})
Vous pouvez utiliser async.forEachOf
- il appelle le rappel de son itérateur avec l'index comme second argument.
> async.forEachOf(['a', 'b', 'c'], function () {console.log(arguments)});
{ '0': 'a', '1': 0, '2': [Function] }
{ '0': 'b', '1': 1, '2': [Function] }
{ '0': 'c', '1': 2, '2': [Function] }
voir le docs pour plus d'infos
Depuis que cette réponse a été écrite, il existe maintenant une meilleure solution. S'il vous plaît voir la réponse de xuanji pour plus de détails
Merci à @genexp pour un exemple simple et concis dans les commentaires ci-dessous ...
async.each(someArray, function(item, done){
console.log(someArray.indexOf(item));
});
Après avoir lu la documentation, je soupçonnais qu’il n’y avait aucun moyen d’accéder à un entier représentant la position dans la liste ...
Applique une fonction itérateur à chaque élément d'un tableau, en parallèle. L'itérateur est appelé avec un élément de la liste et un rappel pour la fin de l'opération. Si l'itérateur transmet une erreur à ce rappel, le rappel principal de chaque fonction est immédiatement appelé avec l'erreur.
Notez que, puisque cette fonction applique l'itérateur à chaque élément en parallèle, rien ne garantit que les fonctions de l'itérateur seront exécutées dans l'ordre.
J'ai donc creusé un peu plus profondément ( Lien au code source )
async.each = function (arr, iterator, callback) {
callback = callback || function () {};
if (!arr.length) {
return callback();
}
var completed = 0;
_each(arr, function (x) {
iterator(x, only_once(function (err) {
if (err) {
callback(err);
callback = function () {};
}
else {
completed += 1;
if (completed >= arr.length) {
callback(null);
}
}
}));
});
};
Comme vous pouvez le constater, un nombre completed
est mis à jour à la fin de chaque rappel, mais aucune position d'index réelle.
Incidemment, la mise à jour du compteur completed
ne pose pas de problème de concurrence car JavaScript est purement à thread unique sous les couvertures.
Edit: Après avoir creusé davantage dans l'itérateur, il vous semble que pourrait pouvoir référencer une variable index
grâce aux fermetures ...
async.iterator = function (tasks) {
var makeCallback = function (index) {
var fn = function () {
if (tasks.length) {
tasks[index].apply(null, arguments);
}
return fn.next();
};
fn.next = function () {
return (index < tasks.length - 1) ? makeCallback(index + 1): null;
};
return fn;
};
return makeCallback(0);
};
Utilisez simplement async.forEachOf()
.
async.forEachOf(arr, function(value, index, callback) { ... }, ...
Pour plus de détails, voir documentation ici .
La méthode async.each()
itérera le tableau dans parallel et ne fournira pas l'index de l'élément au rappel itératif.
Alors quand tu as:
function( done ){
async.each(
someArray,
function( item, cb ){
// ... processing
cb( null );
},
function( err ){
if( err ) return done( err );
// ...
done( null );
}
);
}
Pendant que vous POUVEZ utiliser Array.indexOf()
pour le trouver:
function( done ){
async.each(
someArray,
function( item, cb ){
// ... processing
var index = someArray.indexOf( item );
cb( null );
},
function( err ){
if( err ) return done( err );
// ...
done( null );
}
);
}
Cela nécessite une recherche en mémoire dans le tableau pour CHAQUE itération du tableau. Pour les baies de grande taille, cela peut tout ralentir considérablement.
Une meilleure solution de contournement pourrait être d'utiliser async.eachSeries()
à la place et de garder l'index vous-même:
function( done ){
var index = -1;
async.eachSeries(
someArray,
function( item, cb ){
// index is updated. Its first value will be `0` as expected
index++;
// ... processing
cb( null );
},
function( err ){
if( err ) return done( err );
// ...
done( null );
}
);
}
Avec eachSeries()
, vous avez la garantie que les choses se feront dans le bon ordre.
Une autre solution de contournement, qui est le premier choix du responsable d'async , consiste à itérer avec Object.keys:
function( done ){
async.each(
Object.keys( someArray ),
function( key, cb ){
// Get the value from the key
var item = someArray[ key ];
// ... processing
cb( null );
},
function( err ){
if( err ) return done( err );
// ...
done( null );
}
);
}
J'espère que ça aide.
someArrayWithIndexes = someArray.map(function(e, i) {return {obj: e, index: i}}); async.each(someArrayWithIndexes , function(item, done){ console.log("Index:", item.index); console.log("Object:", item.obj); });