Return 遍历文件夹函数的最终值
Return final value from traversing folder function
问题:为什么 var things
return 不是来自 walk()
函数之外的值?我该如何解决?
假设:这是异步的,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();
Q. Why won't a var things return a value from outside the walk() function?
R。因为 walk
没有 return 任何东西(看一看,你会发现它是一个 void
函数)。
即使你把它变成一个 Promise,你也不能像这样使用它:
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的小库,它会帮助你实现几乎ES7async/await
所提出的,而且它会主要使用native代码,所以可读性和性能都非常好:
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。
问题:为什么 var things
return 不是来自 walk()
函数之外的值?我该如何解决?
假设:这是异步的,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();
Q. Why won't a var things return a value from outside the walk() function?
R。因为 walk
没有 return 任何东西(看一看,你会发现它是一个 void
函数)。
即使你把它变成一个 Promise,你也不能像这样使用它:
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的小库,它会帮助你实现几乎ES7async/await
所提出的,而且它会主要使用native代码,所以可读性和性能都非常好:
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。