以递归和异步方式使用`fs.readdir()`,在完成时运行一些东西

时间:2015-07-02 22:01:26

标签: node.js asynchronous recursion

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

这就是我写的 - 但它被打破了。我错误地确信异步的结束只会被调用一次,而且只会在最后调用。但是,由于for /f "tokens=1,* delims=:" %a in ('netsh wlan show interface^|find "Name"') do @for /f "tokens=*" %x in ("%b") do @echo netsh wlan set profileorder name="%WIFI%" interface="%x" priority=1 以递归方式调用自身,因此循环的结束"函数实际上运行了几次(每个目录一次)。

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(); }); 即将结束,但这只是一个侥幸。如果循环中的任何内容花费的时间超过预期,则会触发process.exit()。

对于我要做的事情,这段代码可能发生的最小变化是什么?

1 个答案:

答案 0 :(得分:0)

递归调用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

  })
}