2014-02-28 62 views
0

在Mixu的Node.js書籍中,有一篇關於控制流程的非常棒的章節。以下模式允許您鏈接異步請求以確保在調用下一個事件之前事件已完成。我想修改它,以便來自一個異步請求的響應可以作爲參數傳遞給下一個。基於JavaScript系列的控制流程

任何想法?

http://book.mixu.net/node/ch7.html http://jsfiddle.net/B7xGn/

function series(callbacks, last) { 
    var results = []; 
    function next() { 
    var callback = callbacks.shift(); 
    if(callback) { 
     callback(function() { 
     results.push(Array.prototype.slice.call(arguments)); 
     next(); 
     }); 
    } else { 
     last(results); 
    } 
    } 
    next(); 
} 
// Example task 
function async(arg, callback) { 
    var delay = Math.floor(Math.random() * 5 + 1) * 100; // random ms 
    console.log('async with \''+arg+'\', return in '+delay+' ms'); 
    setTimeout(function() { callback(arg * 2); }, delay); 
} 
function final(results) { console.log('Done', results); } 

series([ 
    function(next) { async(1, next); }, 
    function(next) { async(2, next); }, 
    function(next) { async(3, next); }, 
    function(next) { async(4, next); }, 
    function(next) { async(5, next); }, 
    function(next) { async(6, next); } 
], final); 
+1

你可以考慮使用承諾:https://github.com/kriskowal/q –

+1

或[異步](https://github.com/caolan/async)模塊,特別是'.waterfall()'函數。 – clay

回答

1

您可以更改next函數簽名,這樣就可以通過它result。以下是你如何做到這一點。

function series(callbacks, last) { 
    var results = []; 
    function next(result) { 
    var callback = callbacks.shift(); 
    if(callback) { 
     callback(function(result) { 
     results.push(Array.prototype.slice.call(arguments)); 
     next(result); 
     }, result); 
    } else { 
     last(results); 
    } 
    } 
    next(); 
} 
// Example task 
function async(arg, callback) { 
    var delay = Math.floor(Math.random() * 5 + 1) * 100; // random ms 
    console.log('async with \''+arg+'\', return in '+delay+' ms'); 
    setTimeout(function() { callback(arg * 2); }, delay); 
} 

function final(results) { console.log('Done', results); } 

series([ 
    function(next) { async(1, next); }, 
    function(next, result) { console.log('result: ', result); async(2, next); }, 
    function(next, result) { console.log('result: ', result); async(3, next); }, 
    function(next, result) { console.log('result: ', result); async(4, next); }, 
    function(next, result) { console.log('result: ', result); async(5, next); }, 
    function(next, result) { console.log('result: ', result); async(6, next); } 
], final); 

編輯:

爲了能夠通過多個結果,你可以簡單地改變一系列功能:

function series(callbacks, last) { 
    var results = []; 
    function next() { 
    var callback = callbacks.shift(), args; 
    if(callback) { 
     callback.apply(this, (args = [ 
     function() { 
      results.push(Array.prototype.slice.call(arguments)); 
      next.apply(this, arguments); 
     } 
     ]).concat.apply(args, arguments)); 
    } else { 
     last(results); 
    } 
    } 
    next(); 
} 
+0

最好。回答。永遠。順便說一句,有沒有辦法將多個參數返回給回調,並在下一個函數中讀取它們?說,回調(2,富)? – 4m1r

+0

@ 4m1r很高興我能幫忙,我已經更新了處理多個參數的答案。 – plalx

+0

再次感謝@plalx。超酷的答案。關於你的編輯,我實際上試圖找到一種從回調中的多個參數異步返回的方式。但是,由於我只能傳遞一個對象字面值作爲結果,因此這可能不是很好的設計。無論如何,你的編輯似乎是一個更加優雅的解決方案。在我的系列中,我將結果直接傳遞給下一個函數,例如async(result,next)。很棒。你想爲世界做一個忙,並幫助我們明白究竟是什麼使這項工作? – 4m1r