caolanのasync.js ライブラリ、具体的には.eachメソッドを使用しています。
イテレータのインデックスにどのようにアクセスしますか?
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
})
async.forEachOf
を使用できます。2番目の引数としてインデックスを使用してイテレータコールバックを呼び出します。
> 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] }
詳細については docs を参照してください
この答えを書いて以来、より良い解決策があります。詳細は xuanjiの答え をご覧ください
以下のコメントの簡単で簡潔な例については、@ genexpに感謝します...
async.each(someArray, function(item, done){
console.log(someArray.indexOf(item));
});
ドキュメントを読んで、リスト内の位置を表す整数にアクセスする方法がないと思いました...
配列内の各項目に反復関数を適用しますin parallel。反復子は、リストからの項目と終了時のコールバックを使用して呼び出されます。イテレータがこのコールバックにエラーを渡すと、各関数のメインコールバックがすぐにエラーとともに呼び出されます。
この関数はイテレータを各アイテムに並列に適用するため、イテレータ関数が順番に完了する保証はないことに注意してください。
そこで、もう少し掘り下げました( ソースコードリンク )
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);
}
}
}));
});
};
ご覧のとおり、completed
カウントがあり、各コールバックが完了すると更新されますが、実際のインデックス位置は更新されません。
ちなみに、JavaScriptは 純粋にシングルスレッド であるため、completed
カウンターを更新する際の競合状態に問題はありません。
編集:イテレータをさらに掘り下げると、mightがindex
を参照できるようになりますクロージャーのおかげで変数...
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);
};
async.forEachOf()
を使用してください。
async.forEachOf(arr, function(value, index, callback) { ... }, ...
詳細については、ドキュメント here を参照してください。
メソッドasync.each()
は、配列をparallelで繰り返しますが、要素のインデックスを繰り返しコールバックに提供しません。
あなたが持っているとき:
_function( done ){
async.each(
someArray,
function( item, cb ){
// ... processing
cb( null );
},
function( err ){
if( err ) return done( err );
// ...
done( null );
}
);
}
_
それを見つけるにはArray.indexOf()
を使用する必要があります:
_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 );
}
);
}
_
これには、配列のすべての反復のために、配列内のメモリ内検索が必要です。大規模な配列の場合、これによりすべてが非常に遅くなります。
より良い回避策は、代わりにasync.eachSeries()
を使用して、インデックスを自分で追跡することです。
_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 );
}
);
}
_
eachSeries()
を使用すると、正しい順序で処理されることが保証されます。
asyncのメンテナーの最初の選択 である別の回避策は、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 );
}
);
}
_
これがお役に立てば幸いです。
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); });