javascript async.js 每个都在迭代器中获取索引
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17516981/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
async.js each get index in iterator
提问by Kevin
I'm using caolan's async.jslibrary, specifically the .each method.
我正在使用caolan 的 async.js库,特别是 .each 方法。
How do you get access to the index in the iterator?
如何访问迭代器中的索引?
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
})
回答by xuanji
You can use async.forEachOf
- it calls its iterator callback with the index as its second argument.
您可以使用async.forEachOf
- 它使用索引作为第二个参数调用其迭代器回调。
> 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] }
see the docs for more info.
有关更多信息,请参阅文档。
回答by Basic
Update
更新
Since writing this answer, there is now a better solution. Please see xuanji's answerfor details
自从写了这个答案,现在有了更好的解决方案。请参阅璇玑的答案的详细信息
Original
原来的
Thanks to @genexpfor a simple and concise example in the comments below...
感谢@genexp在下面的评论中提供了一个简单而简洁的例子......
async.each(someArray, function(item, done){
console.log(someArray.indexOf(item));
});
Having read the docs, I suspected that there wasn't any way to access an integer representing position in the list...
阅读文档后,我怀疑没有任何方法可以访问表示列表中位置的整数......
Applies an iterator function to each item in an array, in parallel. The iterator is called with an item from the list and a callback for when it has finished. If the iterator passes an error to this callback, the main callback for the each function is immediately called with the error.
Note, that since this function applies the iterator to each item in parallel there is no guarantee that the iterator functions will complete in order.
将迭代器函数并行应用于数组中的每个项目。迭代器使用列表中的项目和完成时的回调调用。如果迭代器将错误传递给此回调,则立即调用每个函数的主回调并带有错误。
请注意,由于此函数将迭代器并行应用于每个项目,因此不能保证迭代器函数将按顺序完成。
So I dug a little deeper (Source code link)
所以我挖得更深一些(源代码链接)
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);
}
}
}));
});
};
As you can see there's a completed
count which is updated as each callback completes but no actual index position.
正如您所看到的,有一个completed
计数会在每个回调完成时更新,但没有实际的索引位置。
Incidentally, there's no issue with race conditions on updating the completed
counter as JavaScript is purely single-threadedunder the covers.
顺便说一下,更新completed
计数器时没有竞争条件问题,因为 JavaScript 在幕后纯粹是单线程的。
Edit:After digging further into the iterator, it looks like you mightbe able to reference an index
variable thanks to closures...
编辑:进一步挖掘到迭代器后,它看起来像你也许能够引用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);
};
回答by Alain Beauvois
回答by Merc
The method async.each()
will iterate the array in parallel, and it doesn't provide the element's index to the iterating callback.
该方法async.each()
将并行迭代数组,并且不向迭代回调提供元素的索引。
So when you have:
所以当你有:
function( done ){
async.each(
someArray,
function( item, cb ){
// ... processing
cb( null );
},
function( err ){
if( err ) return done( err );
// ...
done( null );
}
);
}
While you COULD use Array.indexOf()
to find it:
虽然你可以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 );
}
);
}
This requires an in-memory search in the array for EVERY iteration of the array. For large-ish arrays, this might slow everything down quite badly.
这需要对数组的每次迭代在数组中进行内存搜索。对于大型阵列,这可能会严重减慢一切。
A better workaround could be by using async.eachSeries()
instead, and keep track of the index yourself:
更好的解决方法可能是使用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 );
}
);
}
With eachSeries()
, you are guaranteed that things will be done in the right order.
使用eachSeries()
,您可以保证事情会按正确的顺序完成。
Another workaround, which is the async's maintainer's first choice, is to iterate with Object.keys:
另一种解决方法是使用 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 );
}
);
}
I hope this helps.
我希望这有帮助。
回答by x3mka
- indexOf solution is slow and should not be used for large arrays.
- eachSeries solution by Merc does't make what you want.
- Effective workaround is just to build another array with indexes:
- indexOf 解决方案很慢,不应用于大型数组。
- Merc 的 eachSeries 解决方案无法满足您的需求。
- 有效的解决方法是构建另一个带有索引的数组:
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); });
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); });