nodejs并行callbackdevise模式

我试图find一个很好的模式来执行一堆并行任务。

让我来定义一些任务来举例说明。 任务a, b, c, d, e, f, g执行为a(function(er, ra){//task a returned, ra is result}) ,所以bg

还有一些任务应该在某个任务完成后执行,我们称它们为ab, bc, abc, bd, bcd, af, fg ,表示当ab返回ab(ra, rb)应该一次执行,当bc返回时,应立即执行bc(rb, rc) ,如果abc全部返回,则应执行abc(ra, rb, rc)

对于最简单的情况,如果只有ab ,我可以这样做:

 (function(cb){ var count = 2, _ra, _rb; function update(){if(--count == 0) cb(null, _ra, _rb)} a(function(er, ra){_ra = ra; update()}); b(function(er, ra){_rb = rb; update()}); })(function(er, ra, rb){ ab(ra, rb); }); 

如你所见, ab并行执行,当两者都完成时, ab(ra, rb)执行。

但是我怎样才能做更多的事情来完成很多并行任务呢?

你真正想要的是一个延期的模式,虽然像期货 。

 function defer(f) { // create a promise. var promise = Futures.promise(); f(function(err, data) { if (err) { // break it promise.smash(err); } else { // fulfill it promise.fulfill(data); } }); return promise; } var da = defer(a), db = defer(b), dc = defer(c), dd = defer(d), de = defer(e), df = defer(f), dg = defer(g); // when a and b are fulfilled then call ab // ab takes one parameter [ra, rb] Futures.join(da, db).when(ab); Futures.join(db, dc).when(bc); // abc takes one parameter [ra, rb, rc] Futures.join(da, db, dc).when(abc); Futures.join(db, dd).when(bd); Futures.join(db, dc, dd).when(bcd); Futures.join(da, df).when(af); // where's e ? Futures.join(df,dg).when(fg); Futures.join(da,db,dc,dd,de,df,dg).fail(function() { console.log(":("); }); 

你应该检查步骤( https://github.com/creationix/step )。 这只是一百多行代码,所以你可以阅读整个事情,如果需要的话。

我喜欢的模式看起来像这样:

 function doABunchOfCrazyAsyncStuff() { Step ( function stepA() { a(arg1, arg2, arg3, this); // this is the callback, defined by Step } ,function stepB(err, data) { if(err) throw err; // causes error to percolate to the next step, all the way to the end. same as calling "this(err, null); return;" b(data, arg2, arg3, this); } ,function stepC(err, data) { if(err) throw err; c(data, arg2, arg3, this); } ,function stepDEF(err, data) { if(err) throw err; d(data, this.parallel()); e(data, this.parallel()); f(data, this.parallel()); } ,function stepGGG(err, dataD, dataE, dataF) { if(err) throw err; var combined = magick(dataD, dataE, dataF); var group = this.group(); // group() is how you get Step to merge multiple results into an array _.map(combined, function (element) { g(element, group()); }); } ,function stepPostprocess(err, results) { if(err) throw err; var processed = _.map(results, magick); return processed; // return is a convenient alternative to calling "this(null, result)" } ,cb // finally, the callback gets (err, result) from the previous function, and we are done ); } 

笔记

  • 我的例子也使用了下划线库,“匹配JQuery的tux的领带”: http : //documentcloud.github.com/underscore/
  • 命名每个步骤函数stepXXXXX是一个很好的习惯,以便堆栈跟踪清晰可读。
  • Step可以让你制作强大而优雅的串行和并行执行组合。 这些模式是直截了当的,可以理解的。 如果你需要更复杂的东西,比如“当这些方法中的3个完成时,进入下一步”,认真重新考虑你的devise。 你真的需要这样一个复杂的模式吗? (也许你正在等待法定人数)。 这样一个复杂的模式值得它自己的function。

尝试看看步骤模块和这篇文章。

是的,看stream量控制模块,就像step,chain或flow〜我想在underscore.js中也有类似的东西

一个非常简单的障碍就是这个: https : //github.com/berb/node-barrierpoints

灵活是另一个不错的select。