如何组织一个async.waterfall调用循环

如何组织一个async.waterfall调用循环, 以便每次迭代只在前一个迭代完成之后才开始

到目前为止,我有以下代码:

var hasMoreData = true; async.whilst(function () { // * has more data? return hasMoreData; }, function processData(callback1) { async.waterfall([ function readDataFromSource(callback2) { // * read data readData(function readFinished(data, hasMore) { // * got data hasMoreData = hasMore; callback2(null, data); }); }, function writeDataToDest(data, callback2) { // * write data writeData(data, function writeFinished() { callback2(); }); }, ], function (err) { callback1(err); }); }, function finished(err) { }); 

它是这样工作的:

  • 有更多的数据? (1)
  • 读取数据(1)
  • 有更多的数据? (2)
  • 读取数据(2)
  • 得到数据(1)
  • 写数据(1)

我明白为什么它按这个顺序工作 ,在某些情况下这可能是完全正确的。 但在我的具体情况下,我需要开始一个新的迭代,只有在前一个完成后:

  • 有更多的数据? (1)
  • 读取数据(1)
  • 得到数据(1)
  • 写数据(1)
  • 有更多的数据? (2)
  • 读取数据(2)

PS:我不能读取数组中的所有数据,然后使用async.each处理数组。 我也不能预测外部来源有多less数据。

我不使用async ,而只是看代码,描述和API文档,这似乎是这样做你想要的,而不是使用waterfall

 var hasMoreData = true; async.whilst(function () { // * has more data? return hasMoreData; }, function processData(callback1) { // * read data // blocking i/o operation readData(function readFinished(data, hasMore) { // * got data hasMoreData = hasMore; // * write data // blocking i/o operation writeData(data, function writeFinished() { callback1(); }); }); }, function finished(err) { }); 

现场示例 (使用shims for readDatawriteData ):

 // Shims var datacount = 0; function readData(callback) { // since you said "blocking", busy-wait for a quarter second var done = Date.now() + 250; while (done > Date.now()) { } // but calls like this are almost always async, so we'll complete async ++datacount; setTimeout(function() { callback(datacount, datacount < 3); }, 0); } function writeData(data, callback) { // since you said "blocking", busy-wait for a quarter second var done = Date.now() + 250; while (done > Date.now()) { } // but calls like this are almost always async, so we'll complete async setTimeout(function() { callback(); }, 0); } // The code var hasMoreData = true; async.whilst(function() { // * has more data? snippet.log("has more data?"); return hasMoreData; }, function processData(callback1) { // * read data snippet.log("read data"); // blocking i/o operation readData(function readFinished(data, hasMore) { // * got data snippet.log("got data: " + data + " (more? " + hasMore + ")"); hasMoreData = hasMore; // * write data snippet.log("write data"); // blocking i/o operation writeData(data, function writeFinished() { callback1(); }); }); }, function finished(err) { snippet.log("finished"); }); 
 <!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> <script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/async/1.5.0/async.min.js"></script>