根据stackoverflow上的代码片段,我想读取目录中的所有文件,然后继续。 我已经添加了一个承诺,但这在某种程度上是行不通的。
我的目录包含2个文件,控制台日志输出为:
承诺解决了
文件名内部
文件名内部
里面的readFiles
在readFiles里面
function readFiles(dirname, onFileContent, onError) {
return new Promise((resolve, reject) => {
fs.readdir(dirname, function(err, filenames) {
filenames.forEach(function(filename) {
console.log('inside filenames');
fs.readFile(dirname + filename, 'utf-8', function(err, content) {
onFileContent(filename, content);
});
});
});
});
}
var data = [];
readFiles('datadir/', function(filename, content) {
console.log('inside readFiles');
data.push(filename);
}).then(
console.log('promise resolved');
//proceed handling the data-array
);
答案 0 :(得分:1)
承诺不会首先解决"。在读取第一个文件之前执行对console.log
的调用。
您永远不会在您的承诺上致电resolve
,因此永远不会调用then
。但是,您已将console.log
的结果传递给then
。 console.log
的结果无效。
您可以通过更正问题来测试:
readFiles('datadir/', function(filename, content) {
console.log('inside readFiles');
data.push(filename);
}).then(function(){ // NOTE: addition of function(){..}
console.log('promise resolved');
//proceed handling the data-array
});
您会注意到该消息永远不会写入控制台。
所以这是错的 - 如何解决它。需要一些思考来围绕节点中完全基于异步/承诺的代码。
我假设您要等待所有文件在解决您的承诺之前阅读内容。这有点棘手,因为你有2个异步调用(读取文件列表,然后分别读取它们的内容)。将文件的读取包装成自己的承诺可能更容易。像这样:
function readFile(filePath){
return new Promise((resolve,reject) => {
fs.readFile(filePath, "utf-8", function(err,content) => {
if(err) reject(err)
else resolve({path:filePath, content:content})
});
});
}
对readdir
执行相同操作,以使其也可链接:
function readDirectory(dir){
return new Promise((resolve,reject) => {
fs.readdir(dirname, function(err, filenames) {
if(err) reject(err);
else{
resolve(filenames.map(fn => dir + fn));
}
});
});
}
执行此操作的原因是您可以在Promise.all
上链接以等待所有文件内容。
function readFileContents(dirname) {
return readDirectory(dirname)
.then(files =>
Promise.all(files.map(file => readFile(file))
);
}
用法:
readFileContents('datadir/').then(files => {
files.forEach(file => {
console.log(file.path, file.content.length);
});
});