在node.js中,我知道array.forEach正在阻塞。
我需要遍历一个数组并构建一个这样的字符串:
var rarray = ['test', 'test2'];
var rstring = '';
rarray.forEach(function(e, i){
rstring = rstring + i + e;
});
return rstring;
我该如何异步进行?
答案 0 :(得分:1)
在这种情况下,您可能不需要将此代码转换为异步版本。
假设,或者对于非常大的数组,heres是一种将代码转换为异步的方式,或者至少会定期返回主事件循环的方法。
var rarray = ['test', 'test2'];
var rstring = '';
var max = rarray.length;
var current = 0;
process.nextTick(function next() {
rstring = rstring + rarray[current++];
if (current >= max) {
console.log("done", rstring);
} else {
process.nextTick(next);
}
});
实际上,你将它包装在一个函数中,并通过调用完成回调来替换console.log
。
答案 1 :(得分:1)
我可能会补充说,您尝试做的事实上是reduce
。
你可以这样写(doc)
var res = array.reduce(function(prev, current, index) {
return prev + index + current ;
}, '');
异步执行可以这样做
var array = ['one', 'two'];
function reduceAsync(collection, initial, process, callback) {
var i = 0;
var res = initial;
function DO(err, result) {
if(err) return callback(err);
if(i > collection.length) return callback(null, res);
var index = i++;
var value = collection[index];
process(res, value, index, collection, DO);
}
DO(null, res);
}
reduceAsync(array, '', function(previous, current, index, collection, callback) {
setTimeout(function() {
callback(null, previous + index + current);
}, 10); // wait 10 ms
}, function finalResult(err, result) {
console.log(result);
})
或者,您知道,您可以使用async.reduce
答案 2 :(得分:0)
Pascal的答案基本上是一种合作多线程(见Wikipedia: Thread)。
很难说没有测量,但我猜想抢占式多线程会为这种性质的东西提供更好的吞吐量,因为编译器有机会进行循环优化(不确定是否会在上面的代码中特别发生),并且操作系统可能更准确地决定任务切换的频率。您似乎可以在node.js中执行Web Worker Threads。
有人有基准吗?
答案 3 :(得分:0)
如果要将async模块与上面的代码一起使用,您仍然会得到同步代码。异步模块允许您避免回调地狱并管理您的回调。它不会使某些同步异步。要实现这一点,你需要像在Pascal的回答中那样使用process.nextTick。
如果您对数组中的每个项目进行了一些额外的异步处理,并且希望在保留顺序的同时聚合每个操作的结果,那么您可以使用async.eachSeries,如下所示:
var async = require('async');
var rarray = ['test', 'test2'];
var rstring = '', i = 0;
async.eachSeries(rarray, function(item, callback){
rstring += (i++) + item;
callback();
}, function(err){
console.log(rstring);
}
);
如果您不了解事物的顺序,那么您可以使用async.each,它将并行执行您的异步处理函数。