问题:为什么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();
答案 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,你可以使用:
但是,如果您已经使用最新版本的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。