例如,我想编写一个测试用例,它需要跟踪一系列调用的状态。
我可以得到这样的东西:
async_fun(function () {
// Do something ...
async_fun(function () {
// Do something ...
async_fun(function () {
// Do something ...
// ...
});
});
});
async_fun();
当我需要运行一个大循环时,我可以在下面创建一个tail recursion:
function helper (mount) {
async_fun(function (){
if (mount) return;
// Do something ...
helper(mount--);
});
}
helper(10000);
但是,我听说V8引擎没有tail call的优化,所以它可能会耗尽RAM。是否有更好的设计模式来完成这项任务?
PS:请不要第三个lib。我想要一个原生的解决方案。
答案 0 :(得分:2)
对于您的第二个示例,我建议您使用事件。如果使用已注册的事件以及全局(或闭包)计数器,它将使调用堆栈不会增长,但实现相同的逻辑。假设countDown方法执行一些异步工作,只需将此异步工作传递给在线发出下一个事件的回调。
var events = require("events");
function recursiveCountDown(someVariable) {
var counter = someVariable;
var eventEmitter = new events.EventEmitter();//create a new event object, so we can have lots of these running potentially without interfering with one another!
var eventName = 'count';
function countDown() {
someVariable--;
console.log(someVariable);
if(someVariable) eventEmitter.emit(eventName);
}
eventEmitter.on(eventName, countDown);
eventEmitter.emit(eventName);
}
recursiveCountDown(1000);
对于您的第一个问题,有几个流控制库可用。说实话,你已经用一种更讨厌的方式组织了这个。你可以做一些组织的事情来使这个“更好”,但他们最终看起来只是稍微好一些。没有办法避免这种逻辑流,从我的角度来看,我更喜欢看事情是如何执行的。但是,这只是一种意见。您可以查看一些流控制库,ASYNC似乎是标准。基本上,它允许的是,您可以像在线执行一样呈现您的函数,尽管事实上它们在内部被包装并作为连续回调执行,就像您上面提到的那样。我更喜欢以下习语:
function doABunchOfAsyncWorkInSeries(arg, callbackToMainEventLoop) {
var sharedByAll = 'OUTPUT: '
setTimeout(function(){
console.log(sharedByAll + arg);
asyncFun2('a different string');
}, 1000);
function asyncFun2(arg2) {
setTimeout(function() {
console.log(sharedByAll + arg2);
asyncFun3('final string');
}, 2000);
}
function asyncFun3(arg3) {
setTimeout(function(){
console.log(sharedByAll +arg3);
callbackToMainEventLoop('FINISHED');
}, 3000);
}
}
doABunchOfAsyncWorkInSeries('first string', function(arg) {
console.log('The program is finished now. :' + arg);
});
请注意,逻辑流程基本相同,但函数是按顺序编写的。很明显,一个人正在执行另一个,尽管事实上doSomeWork ....函数可以是异步的,而不会影响逻辑流程。在你的例子中你做同样的事情,但每个连续的函数在其闭包中包含另一个函数......没有理由这样做。这看起来有点干净。同样,如果你不介意库为你做这样的事情,为了简化你的语法,请查看Async。但在内部,这就是Async正在做的事情。我真的很喜欢这种语法。