1

在 node.js 中,我知道 array.forEach 是阻塞的。

我需要遍历一个数组并构建一个这样的字符串:

var rarray = ['test', 'test2'];
var rstring = '';
  rarray.forEach(function(e, i){
  rstring = rstring + i + e;
});
return rstring;

我如何异步执行?

4

4 回答 4

1

在这种情况下,您可能不需要将此代码转换为其异步版本。

假设地,或者对于非常大的数组,这是一种将代码转换为异步代码的方法,或者至少可以定期返回主事件循环。

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通过调用完成回调来替换。

于 2013-03-01T06:36:08.737 回答
1

我可能会补充一点,你想要做的实际上是调用reduce. 你可以这样写(文档

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

于 2013-03-01T10:23:45.693 回答
0

Pascal 的回答本质上是一种协作多线程(参见Wikipedia: Thread)。

没有测量很难说,但我猜抢占式多线程对于这种性质的事情会有更好的吞吐量,因为编译器有机会进行循环优化(不确定上面的代码会特别发生这种情况),并且操作系统可能更擅长确定任务切换的频率。看起来您可以在 node.js中执行Web Worker Threads 。

有人有基准吗?

于 2013-03-01T06:58:07.683 回答
0

如果你想在上面的代码中使用异步模块,你仍然会得到同步代码。异步模块允许您避免回调地狱并管理您的回调。它不会使某些东西同步异步。要实现这一点,您需要像 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 ,它将并行执行您的异步处理功能。

于 2013-03-01T10:23:16.117 回答