我正在玩Node并遇到一个奇怪的问题(对我来说很奇怪)。自从我做了任何Javascript以来已经很长时间了,所以这个问题很可能让我盯着我。
我遍历目录中的JSON文本文件列表,解析每个文件中的文本。它正确地在目录中移动;当我使用console.log查看时,每个对象都显示正确。
但是,当我尝试将其推送到数组时,没有任何反应,大小在循环结束时仍然是一个。这感觉就像一个范围问题。
感谢您的任何建议。
app.get("/people/:value1/metrics/:value2", function(req, res) {
var value1 = req.params.value1;
var value2 = req.params.value2;
var personPath = "people/" + value1 + "/" + value2;
var content;
var data = [];
fs.readdir( personPath, function(err, files) {
if(err) {
console.log(err);
}
files.forEach( function (file, index ) {
content = fs.readFileSync(personPath + '/' + file);
console.log(JSON.parse(content)); //Correctly outputs the object.
content = JSON.parse(content);
data.push(content);
});
});
console.log(data.length); //Always 0.
res.send(data);
});
答案 0 :(得分:1)
因为它是这样的异步函数代码:
files.forEach( function (file, index ) {
content = fs.readFileSync(personPath + '/' + file);
console.log(JSON.parse(content)); //Correctly outputs the object.
content = JSON.parse(content);
callback(content);
});
callback(content)
{
data.push(content);
}
答案 1 :(得分:0)
您需要了解异步执行,并将此块放入:
console.log(data.length);
res.send(data);
在fs.readdir
答案 2 :(得分:0)
fs.readdir
是一个异步执行。在console.log(data.length)
执行完成之前,您的fs.readdir
正在执行。
这也意味着您的res.send
也在提前执行。
同步执行
如果您希望保持代码中的操作顺序相同,请考虑使用fs.readdirSync
:
app.get("/people/:value1/metrics/:value2", function(req, res) {
var value1 = req.params.value1;
var value2 = req.params.value2;
var personPath = "people/" + value1 + "/" + value2;
var content;
var data = [];
fs.readdirSync( personPath ).forEach(function(file, index) {
content = fs.readFileSync(personPath + '/' + file);
console.log(JSON.parse(content)); //Correctly outputs the object.
content = JSON.parse(content);
data.push(content); //I'm sure this is push references that are destroyed when out of scope.
});
console.log(data.length); //Always 0.
res.send(data);
});
有关fs.readdirSync的更多信息,请点击此处: https://nodejs.org/api/fs.html#fs_fs_readdirsync_path_options
异步执行
您应该花时间了解有关异步执行的更多信息。这篇文章有一个很好的解释:How does Asynchronous Javascript Execution happen? and when not to use return statement?
如果您将console.log
和res.send
移到fs.readdir
的范围内,这可以解决您的问题:
app.get("/people/:value1/metrics/:value2", function(req, res) {
var value1 = req.params.value1;
var value2 = req.params.value2;
var personPath = "people/" + value1 + "/" + value2;
var content;
var data = [];
fs.readdir( personPath, function(err, files) {
if(err) {
console.log(err);
}
files.forEach( function (file, index ) {
content = fs.readFileSync(personPath + '/' + file);
console.log(JSON.parse(content));
content = JSON.parse(content);
data.push(content);
});
console.log(data.length); //placed within the scope of fs.readdir
res.send(data);
});
});
编辑:另外需要注意的是.forEach
不是异步的。从语法上讲,fs.readdir
和.forEach
都相似,但.forEach
是阻塞方法。这意味着每次迭代都将在下一行执行之前完成。因此,在<{em> console.log
之后移动res.send
和.forEach
右会产生预期效果。
有关.forEach
的更多信息,请访问JavaScript, Node.js: is Array.forEach asynchronous?