2014-12-05 62 views
0

我需要執行相當於async.eachSeries()方法,但我不想添加依賴項,如require('async')在不使用異步模塊的節點中異步,是否有更好的方法?

所以我想出下面的實現,我想知道是否有更好的方法來做到這一點?

it 'String::start_Process_Capture_Console_Out', (done)-> 

    runTest = (testData,next)-> 
     name   = testData.process_Name 
     parameter  = testData.process_Parameter 
     expected_Data = testData.expected_Data 
     name.start_Process_Capture_Console_Out parameter, (data)-> 
      data.assert_Is(expected_Data) 
      next() 

    runTests = (testsData, next)-> 
     if testsData.empty() 
      next() 
     else 
      runTest testsData.pop(),()-> runTests(testsData, next) 

    testsData = [ 
        {process_Name: 'echo' , process_Parameter: 'hello'  , expected_Data:'hello\n' } 
        {process_Name: 'echo' , process_Parameter: ['hello','me'], expected_Data:'hello,me\n' } 
        {process_Name: 'git' , process_Parameter: ['xyz'  ], expected_Data:'git: \'xyz\' is not a git command. See \'git --help\'.\n' } 
        {process_Name: 'ls' , process_Parameter: '.'   , expected_Data:'LICENSE\nREADME.md\nindex.js\nnode_modules\npackage.json\nsrc\ntest\n' } 
       ]  

    runTests(testsData, done) 

僅供參考這裏的start_Processstart_Process_Capture_Console_Out串原型方法

String::start_Process = (args...)-> 
    args ?= [] 
    return child_process.spawn(@.str(),args) 


String::start_Process_Redirect_Console = (args...)-> 
    args ?= [] 
    childProcess = @.start_Process(args) 
    childProcess.stdout.on 'data', (data)->console.log(data.str().trim()) 
    childProcess.stderr.on 'data', (data)->console.log(data.str().trim()) 
    return childProcess 

String::start_Process_Capture_Console_Out = (args... , callback)-> 
    consoleData = "" 
    childProcess = @.start_Process(args) 
    childProcess.stdout.on 'data', (data)->consoleData+=data 
    childProcess.stderr.on 'data', (data)->consoleData+=data 
    childProcess.on 'exit',()-> 
     callback(consoleData) 
    return childProcess 

一種解決方案將是一個原型添加到Array類,也可以叫做async_Each_Series,這樣我們可以只是:

testsData = [ 
        {process_Name: 'echo' , process_Parameter: 'hello'  , expected_Data:'hello\n' } 
        {process_Name: 'echo' , process_Parameter: ['hello','me'], expected_Data:'hello,me\n' } 
        {process_Name: 'git' , process_Parameter: ['xyz'  ], expected_Data:'git: \'xyz\' is not a git command. See \'git --help\'.\n' } 
        {process_Name: 'ls' , process_Parameter: '.'   , expected_Data:'LICENSE\nREADME.md\nindex.js\nnode_modules\npackage.json\nsrc\ntest\n' } 
       ]  

    testsData.async_Each_Series(runTest, done) 
+0

在我看來,你已經實現了['eachSeries'(https://github.com/caolan/async#eachseriesarr-iterator-callback),不' each'? – Bergi 2014-12-05 04:09:41

+1

通過什麼標準「更好」?如果你想關注可重用性和可讀性,不要重新發明輪子,只需要「異步」。這沒有什麼壞處。 – Bergi 2014-12-05 04:11:03

+0

@Bergi是我實現了每個系列(將更新與修復該職位) – 2014-12-15 11:36:08

回答

1

nodejs Array類已經有forEach方法,但是我t不與帶回調

[1,2,3,4].forEach (i) -> 
    console.log i 

如果你需要回調,寫(JS這個時候)

function applyVisitor(data, visitor, next) { 
    // ... 
} 

或者你也可避免依賴性和剪切和過去的副本相關的代碼到你。

(編輯:簡而言之,是的,有一個更好的方式 - 寫一個通用的迭代器並使用它 對於這些測試,不寫專用循環只爲這)

我(在https://npmjs.org/package/aflow也)實施applyVisitor

/** 
* Repeatedly call func until it signals stop (returns truthy) or err. 
* Func is passed just a standard callback taking err and ret. 
* Returns via its callback the truthy value from func. 
*/ 
function repeatUntil(func, callback) { 
    'use strict'; 

    callback = callback || function() {}; 

    function _loop(func, callback, callDepth) { 
     try { 
      func(function(err, stop) { 
       if (err || stop) return callback(err, stop); 
       if (callDepth < 40) _loop(func, callback, callDepth + 1); 
       else setImmediate(function() { _loop(func, callback, 0); }); 
      }); 
     } 
     catch (e) { callback(e); } 
    } 
    // note: 2.5x faster if callback is passed in to _loop vs pulled from closure 

    _loop(func, callback, 0); 
} 


/** 
* visitor pattern: present all items to the visitor function. 
* Returns just error status, no data; to capture the results, 
* wrapper the visitor function. 
*/ 
function applyVisitor(dataItems, visitorFunction, callback) { 
    'use strict'; 

    if (!Array.isArray(dataItems)) { 
     return callback(new Error("expected a data array, but got " + typeof data)); 
    } 

    var next = 0; 
    repeatUntil(
     function applyFunc(cb) { 
      if (next >= dataItems.length) return cb(null, true); 
      visitorFunction(dataItems[next++], function(err) { 
       cb(err, err); 
      }); 
     }, 
     function(err, stop) { 
      callback(err); 
     } 
    ); 
}