从遍历文件夹功能返回最终值

时间:2015-10-02 02:10:09

标签: javascript node.js recursion filesystems

问题:为什么var things不会从walk()函数外部返回值?我该如何解决?

Hypothosis:这是异步的,console.log发生得太早了。这将引导我如何将其设为Promise(我正在使用节点4.1.1)

var walk = function(dir, done) {
  var results = [];
  fs.readdir(dir, function(err, list) {
    if (err) return done(err);
    var i = 0;
    (function next() {
      var file = list[i++];
      if (!file) return done(null, results);
      file = dir + '/' + file;
      fs.stat(file, function(err, stat) {
        if (stat && stat.isDirectory()) {
          walk(file, function(err, res) {
            results = results.concat(res);
            next();
          });
        } else {
          results.push(file);
          next();
        }
      });
    })();
  });
};

function traverseDirectories() {
    var things = walk('src/', function(err, results){
        if(err) throw err;
        console.log(results) // ['dir/thing.png', 'dir/thing2.png']
        return results;
    });
    console.log(things) // undefined
};
traverseDirectories();

1 个答案:

答案 0 :(得分:1)

  

Q值。为什么var = thing会从walk()函数外部返回一个值?

R上。由于walk没有返回任何内容(请注意,您会发现它是void函数。)

即使你把它变成了承诺,你仍然无法像以下那样使用它:

var things = walk(...);
console.log(things);

因为Promise是可以的,并且仍然是异步的,所以它将是:

walk(...).then(function(things) {
  // do something with things here
});

要做你想做的事,你需要的东西在当前的Javascript中还不存在。

有一个ES7 proposal of native async/await将成为回调天堂,但atm,你可以使用:

  • Async/Await library(这是一个了不起的图书馆,但离本地人很远,而且表现并不酷)
  • ES7转录程序 - 您今天可以编写ES7代码,它可以转换为ES5(例如Babel

但是,如果您已经使用最新版本的NodeJS(4.0.0作为撰写时) - 如果您不是,那么您真的应该 - 实现您想要的最佳方式是使用生成器

结合名为 co 的小型库,它将帮助您实现ES7 async/await提出的几乎所有内容,并且它将主要使用本机代码,因此两者都具有可读性并且表现非常好:

var co = require('co');

var traverseDirectories = co(function *traverseDirectories() {
  var things = yield walk('src/');
  console.log(things) // there we go!
});

function walk(dir, results) {
  return new Promise(function(resolve, reject) {
    fs.readdir(dir, function(err, list) {
      if (err)
        reject(err);

      var i = 0;
      (function next() {
        var file = list[i++];
        if (!file) resolve(results);
        file = dir + '/' + file;
        fs.stat(file, function(err, stat) {
          if (stat && stat.isDirectory()) {
            walk(file).then(function(res) {
              results = results.concat(res); 
              next();
            });
          } else {
            results.push(file);
            next();
          }
        });
      })();
    });
  });
}

您可以阅读有关此主题的更多信息in this awesome Thomas Hunter's blog post