Reputation: 25
I am trying to read some files and store their name in an array in nodejs. I have made a function. It reads the file, and prints them out in the console, but the output of the array is []. I am assuming it is because node.js is asynchronous, but I thought a callback would fix it?
readCurdir("./uploads/", curDirReadFinn);
function readCurdir(dir, callback){
var tmpArray = [];
fs.readdir(dir, function(err, files){
if(err){
if(err.code==='EISDIR'){}
else{
console.log(err);
}
return;
}
files.forEach(function(file){
fs.readFile(dir + file, 'utf-8', function(err, data){
if(err){
if(err.code==='EISDIR'){}
else{
console.log(err);
}
return;
}
tmpArray.push(file);
console.log(file); //this prints
});
});
});
callback(tmpArray);
}
function curDirReadFinn(array){
console.log(array); //Output: []
}
I have also tried this:
files.forEach(function(file){
fs.readFile(dir + file, 'utf-8', function(err, data){
if(err){
if(err.code==='EISDIR'){}
else{
console.log(err);
}
return;
}
tmpArray.push(file);
counter++;
if(counter === files.lenght){
callback(tmpArray);
}
});
});
Upvotes: 1
Views: 149
Reputation: 38826
You've got the right idea with your second attempt. After I'd simplified it, it then works perfectly:
function readCurdir(dir, callback){
var tmpArray = [];
fs.readdir(dir, function(err, files) {
if (err) {
return console.log(err);
}
var counter = files.length;
files.forEach(function(file) {
fs.stat(path.join(dir, file), function(err, stats) {
if (err) {
console.log(err);
}
else if (stats.isFile()) {
tmpArray.push(file);
}
--counter === 0 && callback(tmpArray);
});
});
});
}
You can simplify it even further (and propagate errors more easily) using the async module:
async.each(files, function(file, cb) {
fs.stat(path.join(dir, file), function(err, stats) {
if (err) {
return cb(err);
}
else if (stats.isFile()) {
tmpArray.push(file);
}
cb();
});
}, function(err) {
callback(err, tmpArray)
});
Upvotes: 2
Reputation: 1337
Asynchronous code strikes again! fs.readdir()
is asynchronous. Your callback
method is called separate from the execution of fs.readdir()
. That's why your tmpArray
is empty when you log it in your callback method curDirReadFinn()
.
There are some ways to fix your problem:
Ready your directory and files synchronously. NodeJS has methods for that. See here: https://nodejs.org/api/fs.html#fs_fs_readdirsync_path_options
As @Thomas mentioned, you can make use of stat
and isFile()
to get it over with faster. In general eliminate the need for heavy asynchronous code.
Use Promises!
Upvotes: 1