【问题标题】:Using `fs.readdir()` recursively and asynchronously, running something when finished递归和异步使用`fs.readdir()`,完成后运行一些东西
【发布时间】:2015-07-03 07:08:58
【问题描述】:

我正在尝试使用 fs.readdir 访问一棵树。棘手的部分是我希望脚本在访问完成后运行一次一次

这是我写的——但它坏了。我错误地认为 async 的结束只会被调用一次,而且只会在结束时被调用。但是,由于build() 递归调用自身,“循环结束”函数实际上会运行多次(每个目录一次)。

  var p = require('path');
  var fs = require('fs');

  var build = exports.build = function( dirPath, cb ){

  if( typeof dirPath === 'function' ){
    cb = dirPath;
    dirPath = '.';
  }

  // Read all of the files in that directory
  fs.readdir( dirPath, function( err, fileNames ){
    if( err ) return cb( err );

    async.eachSeries(
      fileNames,
      function( fileName, cb ){

        console.log( "Found:", fileName );

        fs.lstat( p.join( dirPath, fileName ), function( err, fileStat ){
          if( err ) return cb( err );

          // It's a directory: rerun the whole thing in that directory
          if( fileStat.isDirectory() ){
            log( "File is a directory. Entering it and running" );
            return build( p.join( dirPath, fileName), cb );
          } else {
            return cb( null );
          }
        })
      },

      function( err ){
        if( err ) return cb( err );

        // PROBLEM: This will run several times
        console.log("I WANT THIS TO HAPPEN ONLY ONCE");
        cb( null );
      }
    ); // End of async cycle

  })
}

build( function( err ){
  console.log("RESULT:", err );
  process.exit();
});

此时,RESULT: 的写作即将结束,但这是侥幸。如果循环中的任何事情花费的时间比预期的要长,process.exit() 将触发。

为了做我想做的事,对这段代码的最小可能更改是什么?

【问题讨论】:

    标签: node.js asynchronous recursion


    【解决方案1】:

    您可以在递归调用build 时传递第三个参数。然后在最后的回调中检查该参数是否未定义,因为您在第一次调用函数时没有发送此参数:

    var build = exports.build = function( dirPath, cb, recursing ){
    
      if( typeof dirPath === 'function' ){
        cb = dirPath;
        dirPath = '.';
      }
    
      // Read all of the files in that directory
      fs.readdir( dirPath, function( err, fileNames){
        if( err ) return cb( err );
    
        async.eachSeries(
          fileNames,
          function( fileName, cb ){
    
            console.log( "Found:", fileName );
    
            fs.lstat( p.join( dirPath, fileName ), function( err, fileStat ){
              if( err ) return cb( err );
    
              // It's a directory: rerun the whole thing in that directory
              if( fileStat.isDirectory() ){
                console.log( "File is a directory. Entering it and running" );
                return build( p.join( dirPath, fileName), cb, true );
              } else {
                return cb( null );
              }
            })
          },
    
          function( err ){
            if( err ) return cb( err );
    
            // PROBLEM: This will run several times
            if(recursing)
              cb(null)
            else{
              console.log("I WANT THIS TO HAPPEN ONLY ONCE");
              cb( null );
            }
          }
        ); // End of async cycle
    
      })
    }
    

    【讨论】:

      猜你喜欢
      • 2021-08-05
      • 1970-01-01
      • 1970-01-01
      • 2012-01-25
      • 1970-01-01
      • 1970-01-01
      • 2016-09-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多