37

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
})
4

6 に答える 6

38

アップデート

この回答を書いて以来、より良い解決策があります。詳細については、 xuanji の回答を参照してください。

オリジナル

以下のコメントのシンプルで簡潔な例について@genexp に感謝します...

async.each(someArray, function(item, done){
    console.log(someArray.indexOf(item));
});

ドキュメントを読んで、リスト内の位置を表す整数にアクセスする方法がないと思った...

反復子関数を配列内の各項目に並列に適用します。イテレータは、リストからの項目と終了時のコールバックで呼び出されます。イテレータがこのコールバックにエラーを渡すと、各関数のメイン コールバックがすぐに呼び出され、エラーが発生します。

この関数はイテレータを各アイテムに並列に適用するため、イテレータ関数が順番に完了するという保証はないことに注意してください。

だから私はもう少し深く掘り下げました(ソースコードリンク

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、各コールバックが完了するたびに更新されるカウントがありますが、実際のインデックス位置はありません。

completedちなみに、 JavaScript は内部で完全にシングル スレッド化されているため、カウンターの更新時に競合状態の問題は発生しません。

編集:イテレータをさらに掘り下げた後、クロージャーのおかげで変数を参照できるように見えます...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);
};
于 2013-07-07T22:40:32.083 に答える
9

を使用するだけasync.forEachOf()です。

async.forEachOf(arr, function(value, index, callback) { ... }, ...

詳細については、こちらのドキュメントを参照してください

于 2016-03-18T06:30:17.133 に答える
3

メソッドasync.each()は配列を並行して反復し、要素のインデックスを反復コールバックに提供しません。

したがって、次の場合:

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 );
    }
  );
}

これが役立つことを願っています。

于 2015-03-08T23:23:53.017 に答える
0
  1. indexOf ソリューションは遅いため、大きな配列には使用しないでください。
  2. Merc による eachSeries ソリューションは、あなたが望むものを作りません。
  3. 効果的な回避策は、インデックスを持つ別の配列を構築することです。
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);
});
于 2015-05-20T20:43:15.493 に答える