var getfiles = function (context) {
var scriptPath = '/var/names/myfolder';
fs.readdir(scriptPath, function (err, files) {
if (err) return context.sendJson(err, 404);
var resultingJson = {};
for (var j = 0; j < files.length; j++) {
subfolder = scriptPath + files[j];
console.log(files[j]);// prints art,creation
fs.readdir(subfolder, function (err, fi) {
//fi prints [artdetails.txt,artinfo.txt]
// [creationdetails.txt,create.txt]
// console.log(files[j]);// prints undefined here
resultingJson[files[j]] = fi;
});
}
console.log(resultingJson); // returing {}
context.sendJson(resultingJson, 200);
});
}
Above code is used to fetch files inside subfolder myfolder, it contains art,creation
and inside this art folder contains files artdetails.txt,artinfo.txt
creation folder contains files creationdetails.txt,create.txt
etc.
Folder and files are fetching successfully but I want to generate a JSON
format like this:
{`art':['artdetails',artinfo],'creation':['creationdetails','create']} format
How it is possible?
I used resultingJson[files[j]] = fi;
but it returns{}.
What is wrong with my code?
You care resetting the value of resultingJson to {} inside a recursive function.
try this code
var getfiles = function (context) {
var scriptPath = '/var/names/myfolder';
var resultingJson = {};
fs.readdir(scriptPath, function (err, files) {
if (err) return context.sendJson(err, 404);
for (var j = 0; j < files.length; j++) {
subfolder = scriptPath + files[j];
console.log(files[j]);// prints art,creation
fs.readdir(subfolder, function (err, fi) {
//fi prints [artdetails.txt,artinfo.txt]
// [creationdetails.txt,create.txt]
// console.log(files[j]);// prints undefined here
resultingJson[files[j]] = fi;
});
}
console.log(resultingJson); // returing {}
context.sendJson(resultingJson, 200);
});
}
There are a few problems here. First and foremost, Felix Kling made the correct observation about readdir
being async, more specifically referring to the inner readdir
within the for loop. Part of what you are seeing is that your console.log and JSON response is occurring before the directories have finished being read. Also what is likely occurring is the context of j
is being lost, likely ending up the last value.
A control flow library like async may help, such as the each method.
var fs = require('fs'),
async = require('async');
var scriptPath = '/var/names/myfolder';
var getfiles = function(context) {
// Read contents of the parent directory
fs.readdir(scriptPath, function(err, files) {
if (err) return context.sendJson(err, 404);
var result = {};
// Asynchronously iterate over the directories
async.each(files, function iterator(directory, next){
var subfolder = scriptPath + directory;
// Read contents of the child directory
fs.readdir(subfolder, function(err, file){
if (err) return next(err);
// Set the property
result[directory] = file;
// Now that we've finished reading these contents,
// lets read the contents of the next child folder
next();
// When there are none left, the `complete` callback will
// be reached and then it is safe to return a JSON string
});
}, function complete(err){
// All children directories have been read
// and the `result` object should be what we expect
if (err) return context.sendJson(err, 404);
context.sendJson(result, 200);
});
});
};
I have tested this by mocking your folder/file structure and it appears to work properly. It produced the following JSON string:
{"art":["artdetails.txt","artinfo.txt"],"creation":["create.txt","creationdetails.txt"]}
The iterators are called in parallel, so the order may switch, but it shouldn't make a difference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With