所以我发现这个问题看起来非常相似,但我完全不理解答案我试图实现它,但我不认识我的代码中答案的模式。 similar question
现在这是我的问题,我有这段代码:
var fs = require('fs');
var index = JSON.parse(fs.readFileSync('../data/7XXX7/index.json', 'utf8'));
window = {};
var indicators = require('./indicators');
var parser = new window.patient.Indicator('tes', 'test');
var i = 0;
function create_indicators() {
var result = [];
fs.readdirSync('../data/7XXX7/files/').forEach(file => {
fs.readFile('../data/7XXX7/files/' + file, 'utf8', function (err, data) {
if (err)
throw err;
let $ = {};
$.poids = parser.poids(data);
$.taille = parser.taille(data);
$.temperature = parser.temperature(data);
$.tension = parser.tension(data);
$.pouls = parser.pouls(data);
$.ps = parser.ps(data);
$.saturation = parser.saturation(data);
for (var j in index.files)
{
if (index.files[j].name === file)
{
$.id = index.files[j].name;
$.date = index.files[j].date;
$.name = index.files[j].IntituleSession;
break;
}
}
if ($.poids || $.taille || $.temperature || $.tension || $.pouls || $.ps || $.saturation)
{
result.push($);
console.log(result); // print the actual state of result
// console.log(i); prints 0 then 1 then ...
i++;
}
});
console.log(i); // prints 0
});
console.log(result); // prints []
return result;
}
let result = create_indicators();
console.log(result); // prints []
它显示:
[]
为什么readFile中的回调函数有它自己的变量?导致它异步?但是当我使用readFileSync时它也不起作用。
如何让结果得到我投入的所有值?当我在result.push($)之后控制日志结果时;它的工作原理使我不是我的解析器,每次我也正确缩进。
答案 0 :(得分:0)
这是你的问题:
fs.readFileSync('../data/7XXX7/files/' + file, 'utf8', function (err, data) {
readFileSync
不会将回调作为参数。它返回数据或引发异常。它是同步的(正如名称中的“同步”所示)并且您正在使用它,就好像它是异步的一样。
参见文档:
答案 1 :(得分:0)
readFileSync 没有回调。解释回调如何在异步 fs.readFile 和 fs.readdir
中工作可能会有所帮助当您进行异步操作时,因为您不知道它何时完成,您将在参数中传入一个函数(回调),并在操作结束时运行它。
fs.readFile('/etc/passwd', function (err, data) {
if (err) throw err;
console.log(data);
});
上面代码中的fs.readFile 将在完成执行时运行函数(错误,数据),并将数据作为第二个参数传入。如果发生错误,它将作为第一个参数传递错误。
您还可以获得一个回调函数,定义解析结束时要执行的操作。回调将需要采取错误和结果。 (如果您需要错误)
读: http://fredkschott.com/post/2014/03/understanding-error-first-callbacks-in-node-js/
所以你的create_indicators函数应该采用回调函数。
fs = require("fs")
function create_indicators(folderPath, callback) {
let result = [];
fs.readdir(folderPath, (err, files) => {
if (err)
callback(err, null); //pass the error to callback if there is any
else {
files.forEach((file, index, filesArray) => {
fs.readFile(file, (err, data) => {
if (err)
callback(err, null); //pass the error to callback if there is any
else {
//.....parse....
result.push(data);
// pass data to callback function when it is the last result
if (result.length == filesArray.length)
callback(null, result);
}
});
});
}
})
}
当你调用它时,传递你想要做的结果和错误作为一个函数。
create_indicators(".", function(err,result){
if (err)
console.error("Got error:", err);
else
console.log("Got result:", result);
//do what you want with the final result
})
一旦你完成了回调工作,请查看Promise,这将使此过程更简洁。阅读:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
答案 2 :(得分:0)
您的代码不会等待文件被读取,并且在继续之前将结果推送到result
。如果你对数组中的项进行异步操作,我建议使用promises并使用Promise.all()
等待每个文件在尝试使用结果之前进行读取和处理。你可以这样做:
function create_indicators() {
const result = fs.readdirSync('../data/7XXX7/files/').map(file =>
new Promise((resolve, reject) => {
fs.readFile('../data/7XXX7/files/' + file, 'utf8', (err, data) => {
if (err) reject(err);
// do whatever
if ($.poids || /* ... */ $.saturation) {
// ...
resolve($); // instead of `result.push($);`
} else {
resolve(); // can't reject for `Promise.all()` to work
}
})
}));
return Promise.all(result).then(items => items.filter(item => item));
}
create_indicators().then(indicators => {
// do something with your list of indicators
}).catch(err => {
// handle error
});
它为目录中的每个文件创建一个承诺,该承诺在处理文件时解析。如果您的条件不满足,则根据项目解决,如果有错误则拒绝(承诺相当于throw
)。由于您只需要符合条件的项目,因此您可以对Promise.all()
的结果进行过滤以除去数组中的任何undefined
(您也可以删除条件检查fs.readFile
回调,如果您愿意,请在过滤器中执行此操作。这将返回一个使用已过滤列表解析的承诺。