2013-03-01 117 views
1

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

我需要遍歷數組,並建立一個像這樣的字符串:

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

怎麼做呢異步?

+0

可能使用異步庫? – Yalamber 2013-03-01 09:22:23

回答

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

+0

如何使用異步模塊? – Yalamber 2013-03-01 09:21:58

+0

像'async'這樣的東西有助於對異步調用進行排序,而不是使某些事物同步爲異步。這就是'process.nextTick()'所能提供的幫助。 – 2013-03-01 10:12:07

0

帕斯卡的答案本質上是一種合作多線程的形式(見Wikipedia: Thread)。

這很難說沒有測量,但我猜想先發制人的多線程將有更好的吞吐量,因爲編譯器有機會進行循環優化(不確定這將發生在上面的代碼專門發生) ,而操作系統可能會更好地決定任務切換的頻率。看起來您可以在node.js中執行Web Worker Threads

任何人都有基準?

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,它會並行地執行你的異步處理函數。

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