Your original implementation has several timing problems. Your .forEach()
loop does not wait for any of the async operations inside it to complete so you end up calling Promise.all()
before the arrays are filled. I would suggest using the fs
operations that have built-in promise support and also use the withFileTypes
option with fs.promises.readdir()
:
class handleFiles {
constructor() {
this.promiseFiles = [];
this.promiseFolders = [];
}
async getFilesAndFolders() {
let files = await fs.promises.readdir("uploads", {withFileTypes: true});
for (let file of files) {
if (file.isFile()) {
this.promiseFiles.push(file.name);
} else if (file.isDirectory()) {
this.promiseFolders.push(file.name);
}
}
return {
sendFiles: this.promiseFiles,
sendFolders: this.promiseFolders
}
}
}
Note: this implementation is a bit odd in that it is BOTH filling this.promiseFiles
and this.promiseFolders
and is returning a promise that resolves to an object containing that data. I'd really suggest you do one or the other. Also, because of this side-effect programming of adding to this.promiseFiles
and this.promiseFolders
, if you call getFilesAndFolders()
more than once, it will create duplicates.
Perhaps you don't need this data in your instance data at all and the method can just return a promise that resolves to the object as so:
class handleFiles {
constructor() {
}
async fillFilesAndFolders() {
const sendFiles = [], sendFolders = [];
let files = await fs.promises.readdir("uploads", {withFileTypes: true});
for (let file of files) {
if (file.isFile()) {
sendFiles.push(file.name);
} else if (file.isDirectory()) {
sendFolders.push(file.name);
}
}
return {
sendFiles,
sendFolders
};
}
}
But, now this is just a static method that doesn't really have anything to do with the class so perhaps it could just be a stand-alone function or a static method.
Step-by-step Description in the 2nd solution:
- Declare local variables
promiseFolders
and promiseFiles
.
- Call
await fs.promises.readdir()
so we can use the promise interface for readdir
.
- Pass the
withFileTypes
option so we get access to isFile()
and isDirectory()
without making an additional call for every file.
- Iterate through the list of
files
and populate the desired promiseFiles
or promiseFolders
array with the file's name.
- Build the returned data structure and return it (which will be the resolved value of the promise returned from the parent
async
function.