3 回答

TA貢獻(xiàn)1789條經(jīng)驗(yàn) 獲得超10個(gè)贊
在node.js中沒有什么是真正的并行,因?yàn)樗菃尉€程的。但是,可以按照您無法事先確定的順序安排和運(yùn)行多個(gè)事件。而數(shù)據(jù)庫訪問等實(shí)際上是“并行”的,因?yàn)閿?shù)據(jù)庫查詢本身在不同的線程中運(yùn)行,但在完成時(shí)會重新集成到事件流中。
那么,如何在多個(gè)事件處理程序上安排回調(diào)?嗯,這是瀏覽器端javascript動畫中使用的一種常用技術(shù):使用變量來跟蹤完成情況。
這聽起來像是一個(gè)黑客,它聽起來可能是混亂的,留下一堆全局變量圍繞著跟蹤,而用較少的語言。但在javascript中我們可以使用閉包:
function fork (async_calls, shared_callback) { var counter = async_calls.length; var callback = function () { counter --; if (counter == 0) { shared_callback() } } for (var i=0;i<async_calls.length;i++) { async_calls[i](callback); }}// usage:fork([A,B,C],D);
在上面的例子中,我們通過假設(shè)async和callback函數(shù)不需要參數(shù)來保持代碼簡單。您當(dāng)然可以修改代碼以將參數(shù)傳遞給異步函數(shù),并讓回調(diào)函數(shù)累積結(jié)果并將其傳遞給shared_callback函數(shù)。
補(bǔ)充答案:
實(shí)際上,即使是這樣,該fork()
函數(shù)也可以使用閉包將參數(shù)傳遞給異步函數(shù):
fork([ function(callback){ A(1,2,callback) }, function(callback){ B(1,callback) }, function(callback){ C(1,2,callback) }],D);
剩下要做的唯一事情是累積A,B,C的結(jié)果并將它們傳遞給D.
更多補(bǔ)充答案:
我無法抗拒。在早餐期間一直想著這個(gè)。這fork()
是累積結(jié)果的實(shí)現(xiàn)(通常作為參數(shù)傳遞給回調(diào)函數(shù)):
function fork (async_calls, shared_callback) { var counter = async_calls.length; var all_results = []; function makeCallback (index) { return function () { counter --; var results = []; // we use the arguments object here because some callbacks // in Node pass in multiple arguments as result. for (var i=0;i<arguments.length;i++) { results.push(arguments[i]); } all_results[index] = results; if (counter == 0) { shared_callback(all_results); } } } for (var i=0;i<async_calls.length;i++) { async_calls[i](makeCallback(i)); }}
這很容易。這fork()
非常通用,可用于同步多個(gè)非同類事件。
Node.js中的示例用法:
// Read 3 files in parallel and process them together:function A (c){ fs.readFile('file1',c) };function B (c){ fs.readFile('file2',c) };function C (c){ fs.readFile('file3',c) };function D (result) { file1data = result[0][1]; file2data = result[1][1]; file3data = result[2][1]; // process the files together here}fork([A,B,C],D);
更新
此代碼是在存在像async.js或各種基于promise的庫之類的庫之前編寫的。我想相信async.js的靈感來自于此,但我沒有任何證據(jù)。無論如何..如果你今天想要這樣做,請看看async.js或promises。只需考慮上面的答案,就async.parallel之類的工作方式做了很好的解釋/說明。
為了完整起見,以下是您如何做到這一點(diǎn)async.parallel
:
var async = require('async');async.parallel([A,B,C],D);
請注意,async.parallel
它與fork
我們上面實(shí)現(xiàn)的功能完全相同。主要區(qū)別在于它將第一個(gè)參數(shù)傳遞給錯(cuò)誤,D
并根據(jù)node.js約定將回調(diào)傳遞為第二個(gè)參數(shù)。
使用promises,我們將其編寫如下:
// Assuming A, B & C return a promise instead of accepting a callbackPromise.all([A,B,C]).then(D);

TA貢獻(xiàn)1850條經(jīng)驗(yàn) 獲得超11個(gè)贊
將異步調(diào)用連接在一起類似于
pthread_join
線程的工作方式。
自述文件顯示了使用自由式或使用Promise模式使用未來子模塊的一些很好的例子。來自文檔的示例:
var Join = require('join') , join = Join() , callbackA = join.add() , callbackB = join.add() , callbackC = join.add();function abcComplete(aArgs, bArgs, cArgs) { console.log(aArgs[1] + bArgs[1] + cArgs[1]);}setTimeout(function () { callbackA(null, 'Hello');}, 300);setTimeout(function () { callbackB(null, 'World');}, 500);setTimeout(function () { callbackC(null, '!');}, 400);// this must be called after all join.when(abcComplete);
添加回答
舉報(bào)