async.waterfall在函数完成之前跳转到结束

时间:2014-05-15 11:52:14

标签: node.js asynchronous underscore.js

希望你们好吗? 我正在深入研究Node.js并且不得不重新学习我以前用于编码的许多方法 - 并且必须重新训练自己以异步方式...我正在编写服务器端脚本(如java POJO),将从命令行运行或从事件触发。

我希望将一个函数的输出(返回)作为下一个的输入,所以我决定使用async.waterfall - 因为我读到这将按顺序执行函数,使用一个函数的输出作为输入另一个......

脚本的想法是遍历给定的文件夹结构,创建一个子文件夹数组,然后将该数组传递给下一个。然后对该数组中的每个路径执行相同操作。我想使用underscore.js和“_.each()”函数,因为它似乎是按顺序迭代数组的好方法。但是这就是我被困住的地方,因为它似乎在工作完成之前通过所有功能落到最后。所以我的逻辑有点偏离......

我使用'walk'函数进入文件夹并返回所有子文件夹..想法是脚本将运行,然后在瀑布的末尾运行'process.exit()'。

代码是:



    async.waterfall([
      function(callback){ /* Get List of Artists from MusicFolder */
        console.log('first->IN');
        walk(musicFolder, function(err, foldersFound) {
          if (err) { return err;}
          _.each(foldersFound, function(folderPath){
            console.log('Folder: ' + folderPath);
          });
          console.log('first->OUT');
          callback(null, foldersFound);
        });
      },
      function(artistsFound, callback){ /* Get List of Albums from Artist Folders */
        var eachLoop=null;
        console.log('second->IN');
        _.each(artistsFound, function(artistPath){
          console.log('second->eachPath:Start:'+artistPath);
          walk(artistPath, function(err, albumsFound) {
            console.log('second->Walk:Found');
            console.log(albumsFound);
            if (err) { console.log(err);}
            _.each(albumsFound, function(albumPath){
              eachLoop++;
              console.log('second->Walk:each:'+eachLoop);
            });
            console.log('second->Walk:End');
          });
          console.log('second->eachPath:End:'+artistPath);
        });
        console.log('second->OUT');
        callback(null, albumsFound);
      },
      function(paths, callback){
        console.log('third->IN');
        console.log('third->OUT');
        callback(null, paths);
      }
    ], function (err, result) {
        console.log('last->IN');
        console.log(result);
        console.log('last->OUT');
    //    process.exit();
    });

我在示例中注释掉了'process.exit()'。

如果我取消注释'process.exit()',我会得到以下输出:

first->IN
Folder: /music/Adele
Folder: /music/Alex Clare
first->OUT
second->IN
second->eachPath:Start:/music/Adele
second->eachPath:End:/music/Adele
second->eachPath:Start:/music/Alex Clare
second->eachPath:End:/music/Alex Clare
second->OUT
third->IN
third->OUT
last->IN
null
last->OUT

我可以看到它在第二个瀑布函数中没有进入'walk'函数,但是完全跳过'walk',即使'walk'在_.each()迭代中。

如果我在最后一个函数中注释掉'process.exit()'命令,我会得到以下内容:

first->IN
Folder: /music/Adele
Folder: /music/Alex Clare
first->OUT
second->IN
second->eachPath:Start:/music/Adele
second->eachPath:End:/music/Adele
second->eachPath:Start:/music/Alex Clare
second->eachPath:End:/music/Alex Clare
second->OUT
third->IN
third->OUT
last->IN
null
last->OUT
second->Walk:Found
[ '/music/Alex Clare/The Lateness of the Hour' ]
second->Walk:each:1
second->Walk:End
second->Walk:Found
[ '/music/Adele/19',
  '/music/Adele/21',
  '/music/Adele/Live At The Royal Albert Hall' ]
second->Walk:each:2
second->Walk:each:3
second->Walk:each:4
second->Walk:End

我承认这令人沮丧。任何帮助都会非常感激,因为我过去一周一直在以各种“异步”形式反复重写这些帮助,并且它们都过早地跳出了函数 - 所以一切都没有了。

提前感谢您的帮助或想法:)

标记

1 个答案:

答案 0 :(得分:0)

您的walk函数似乎是异步的。并且您希望触发并行异步作业,结合结果并向下移动瀑布。因此,您可以将async.waterfallasync.parallel结合起来。你的第二个功能可能如下所示:

function(artistsFound, callback) {
    // some code
    var jobs = [];
    artistsFound.forEach(function(artistPath) {
        jobs.push(function(clb) {
            walk(artistPath, function(err, albumsFound) {
                // some code
                clb(err, albumsFound);
            });
        });
    });
    // some code
    async.parallel(jobs, callback);
}

旁注:您不必使用underscore.js来简单地循环数组。现代JavaScript具有内置.forEach功能。