我有一个函数,其中许多小进程独立发生,但所有这些进程的结果必须进入最终回调。这不是一个非常不合理的情况;这种代码,你不一定提前知道将要运行什么,什么时候,以及多长时间是相当普遍的,但在这之前几个小时之后,我无法找到一种巧妙的方法。我不是要求几个小时的代码时间,只是简单解释如何做到这一点。
下面的wrapper
函数完成了一系列任务,即异步函数,其执行方式是在执行之前不确定将运行什么,何时以及执行多少次。我试图找到一个简单的方法来调用回调(final callback
注释)一旦完成它们,如果它们没有先失败,但在失败时立即退出包装函数。这类情况的示例将如下所示。
// Definition for wrapper function
function wrapper(callback) {
asyncfunction1();
for(/*conditions*/) {
asyncfunction2();
}
asyncfunction3(function(results) {
asyncfunction4(results);
for(res in results) {
asyncfunction5(res);
}
});
}
// Call to wrapper function
wrapper(function(err) { // final callback
if (err) console.log("Failure");
else console.log("Success");
});
wrapper
包含一系列函数(asyncfunction#()
),这些函数必须全部成功完成才能将回调调用为callback(false)
。如果任何一个失败,则调用回调,然后调用callback(true)
并退出整个包装器,而不关闭进程。
我的绊脚石:
答案 0 :(得分:1)
我还建议使用async.js,你会有一些嵌套调用。异步是针对这种类型的事情 - NodeJS中的控制流很棘手。还有其他软件包(promises,其他异步软件包等)。
下面是使用async的示例。请注意,如果您的流可以并行运行,则外部.series
方法可以是.parallel
。我喜欢在外部resultsObj
中传递内容,这些内容会延续到每个异步调用。它可以包含数组,值,对象等。 。 。只是一个持有人。
我也在使用.series
表示法,其中传入了命名函数的对象,而不是函数数组。存储了传递给回调的值,我在asyncFunction4中使用了它。
var resultsObj = {};
async.series( {
asyncFunction1: function( seriesCb ) {
//do stuff
seriesCb();
},
asyncFunction2: function( seriesCb ) {
async.each( yourArray2, function( item, eachCb ) {
//do stuff
eachCb();
}, function( errEach ) {
resultsObj.someFlag = true;
seriesCb( errEach );
} );
},
asyncFunction3: function( seriesCb ) {
callAsyncFunction3( function( results3 ) {
async.series( {
asyncFunction4: function( innerSeriesCb ) {
var results4 = "yes";
innerSeriesCb( results4 );
},
asyncFunction5: function( innerSeriesCb ) {
async.each( yourArray5, function( item, eachCb ) {
//do stuff
eachCb();
}, function( errEach ) {
innerSeriesCb( errEach );
} );
}
}, function( innerSeriesErr, innerSeriesResults ) {
console.log("Result value of async4 was " + innerSeriesResults.asyncFunction4 );
seriesCb( innerSeriesErr, innerSeriesResults );
} );
} );
}
}, function( seriesErr, seriesResults ) {
if ( seriesErr ) console.log( "Failure" );
else console.log( "Success. results=" + JSON.stringify( resultsObj ) );
} );
编辑:还有一件事。你会注意到这个控制骨架已经有多大了。这没有代码。拆分您的方法并让它们接受(并使用)典型的NodeJS callback(err)
或callback(err, results)
样式。然后在异步流中,以较短的方式调用它们。它只会使这个大型控制文件更容易管理。
function doSomething( input1, input2, callback ){
if( input1 === input2 ) return callback( new Error("Cannot be equal") );
callback( null, "Success ");
}
async.series( {
asyncFunction1: function( seriesCb ) {
doSomething( 1, 2, seriesCb );
}
}, function( seriesErr, seriesResults ) {
if ( seriesErr ) console.log( "Failure" );
else console.log( "Success" );
} );