我需要执行等效的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_Process
和start_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 :(得分:1)
nodejs Array类已经有一个forEach方法,但它不需要回调
[1,2,3,4].forEach (i) ->
console.log i
如果你需要回调,请写(这次是js)
function applyVisitor( data, visitor, next ) {
// ...
}
或者您也可以避免依赖关系并将相关代码复制到您的身上。
(编辑:简而言之,是的,还有更好的方法 - 编写通用迭代器并使用 对于这些测试,不要为此专门编写专用循环。)
我的applyVisitor实现 (也在https://npmjs.org/package/aflow)
/**
* 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);
}
);
}