Reputation: 10042
Following this snippet I am trying to write a function that loops trough a directory, finds directories, and reads xml file names from those directories (I know that the folder structure will always remain the same). So far my function is working as expected, but when I try to get the return from the function I just get Promise objects.
My code:
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
const path = require('path');
function getFileNames(rootPath) {
// Read content of path
return fs.readdirAsync(rootPath)
// For every file in path
.then(function(directories) {
// Filter out the directories
return directories.filter(function(file) {
return fs.statSync(path.join(rootPath, file)).isDirectory();
});
})
// For every directory
.then(function(directories) {
return directories.map(function(directory) {
// Read file in the directory
return fs.readdirAsync(path.join(rootPath, directory))
.filter(function(file) {
return path.extname(file) == '.XML';
})
.then(function(files) {
// Do something with the files
return files;
});
});
});
}
getFileNames('./XML').then(function(files) {
console.log(files);
});
When I console.log(files)
inside the last .then
function inside getFileNames
, I get the actual arrays of file names in the console. But when I run the code above I get this output:
[ Promise {
_bitField: 0,
_fulfillmentHandler0: undefined,
_rejectionHandler0: undefined,
_promise0: undefined,
_receiver0: undefined },
Promise {
_bitField: 0,
_fulfillmentHandler0: undefined,
_rejectionHandler0: undefined,
_promise0: undefined,
_receiver0: undefined },
Promise {
_bitField: 0,
_fulfillmentHandler0: undefined,
_rejectionHandler0: undefined,
_promise0: undefined,
_receiver0: undefined },
Promise {
_bitField: 0,
_fulfillmentHandler0: undefined,
_rejectionHandler0: undefined,
_promise0: undefined,
_receiver0: undefined },
Promise {
_bitField: 0,
_fulfillmentHandler0: undefined,
_rejectionHandler0: undefined,
_promise0: undefined,
_receiver0: undefined } ]
Why is this happening and how to fix it?
Upvotes: 3
Views: 571
Reputation: 10042
Figured it out, there was one .then too much on the second function:
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
const path = require('path');
function getFileNames(rootPath) {
// Read content of path
return fs.readdirAsync(rootPath)
.then(function(content) {
return content.filter(function(file) {
return fs.statSync(path.join(rootPath, file)).isDirectory();
});
})
// For every directory
.map(function(directory) {
// Read files in the directory
return fs.readdirAsync(path.join(rootPath, directory))
.filter(function(file) {
return path.extname(file) == '.XML';
});
});
}
getFileNames('./XML').then(function(files) {
console.log(files);
});
Upvotes: 0
Reputation: 664297
In the lines
.then(function(directories) {
return directories.map(function(directory) {
return fs.readdirAsync…
you are creating a promise for an array of promises, and that's exactly what you're getting in your final log. Instead of returning an array of promises, you need to return a promise for an array of values - and Promise.all
is exactly what does that:
.then(function(directories) {
return Promise.all(directories.map(function(directory) {
return fs.readdirAsync(…)
…
}));
})
However, in Bluebird it would be more idiomatic to use Promise.map(directories, function(…) { … })
or even the map
method (similar to how you already used .filter
did on the files in each directory):
function getFileNames(rootPath) {
return fs.readdirAsync(rootPath)
.filter(function(file) {
return fs.statAsync(path.join(rootPath, file)).then(function(s) {
return s.isDirectory();
});
})
.map(function(directory) {
//^^^^
return fs.readdirAsync(path.join(rootPath, directory))
.filter(function(file) {
return path.extname(file) == '.XML';
})
.map(function(file) {
// Do something with every file
return file;
});
});
}
Upvotes: 2
Reputation: 29906
This piece of code:
.then(function(directories) {
return directories.map(function(directory) {
return fs.readdirAsync(path.join(rootPath, directory))
...
will return an array of promises to the then callback. An array of promises count as an immediate value here, will not be coerected to a Promise of an array. To convert an array of promises to a promise of an array you could use Promise.all
, but since you are using bluebird, you have a better option:
All you have to do is to use Promise.map
:
.then(function(directories) {
return Promise.map(directories, function(directory) {
return fs.readdirAsync(path.join(rootPath, directory))
...
Upvotes: 0
Reputation: 7406
try this
return getFileNames('./XML').then(function(files) {
console.log(files);
return files;
});
Upvotes: 0