0

createFolder() function is returning an empty array. I am not sure what I am doing wrong but it needs to return the items within project_array

function get_project_folders(){

  return new Promise((resolve, reject)=>{
    fs.readdir(__dirname + '/projects', (error, data1)=>{
      if(error){
        reject(console.log(`Error. Unable to read directory - ${error}`))
      }else{
        resolve(data1)
      }
    })
  })
}
async function createFolder(){
  let list_of_projects = await get_project_folders()
  let project_array = []


  return new Promise((resolve, reject)=>{
    for(let project of list_of_projects){
      let splitProject = project.split("-")
      fs.readdir(__dirname + `/projects/${splitProject[0]}-${splitProject[1]}`, (error, data1)=>{
        if(error){
          console.log('Error. Unable to read directory.')
        }else{
          project_array.push({circuit: splitProject[0], fuse: splitProject[1], pole: data1})
        }
      })
    }
    resolve(project_array)
  })
}
async function testIt(){
  let folderData = await createFolder()
  console.log(folderData)
}

testIt()
sam
  • 1,767
  • 12
  • 15
night_programmer
  • 107
  • 1
  • 11
  • 1
    Have you seen what `get_project_folders` returns? – OliverRadini Nov 01 '21 at 13:42
  • Yes it returns the folder names as desired. Create folder function is the only function that is not returning the data that I need – night_programmer Nov 01 '21 at 13:45
  • 2
    This is an async issue - your last resolve happens before your fs calls have resolved. You should do something like `await Promise.all( list_of_projects.map(...) )` and then resolve your wrapping Promise. – somethinghere Nov 01 '21 at 14:33
  • Does this answer your question? [How to return the response from an asynchronous call](https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – Liam Nov 01 '21 at 14:41

1 Answers1

3

This is a classic, what you are doing is resolving the promise with the empty array before your node fs async methods have resolved. Try this instead:

async function createFolder(){

  const list_of_projects = await get_project_folders();
  const result = await Promise.all( list_of_projects.map(project => new Promise((resolve, reject) => {
    const splitProject = project.split("-");
    fs.readdir(__dirname + `/projects/${splitProject[0]}-${splitProject[1]}`, (error, data1) => {
      if(error){
        console.error('Error. Unable to read directory.');
        resolve( null );
      } else {
        resolve({
          circuit: splitProject[0],
          fuse: splitProject[1],
          pole: data1
        });
      }
    });
  });
  
  // Filter out the errors that resolved as `null`
  return result.filter( Boolean );
  
}

In essence, wrap every fs. call in a promise, then use Promise.all to generate an array of promises. Because Promise.all requires all to be resolved for it to be resolved, make sure you even resolve when there is an error - just return something falsy (in my case null) so you can filter it out later.

somethinghere
  • 16,311
  • 2
  • 28
  • 42
  • 1
    An alternative to wrapping everything yourself would be to `const {promises: {readdir}} = require('fs')` or the same, but written out longer: `const fs2 = require('fs'); const readdir = fs2.readdir;` (using `import` is possible too, of course) & then use just use `await readdir(path)`. Most Node.js internal libraries have an 'official' promise-based variant. – RickN Nov 01 '21 at 14:47
  • Sure, but without knowing the node version that might cause issues at the moment. By which I mean I love the syntax, but it isn’t standard in nodejs yet :( – somethinghere Nov 01 '21 at 14:51
  • `fs.promises` was stable in Node 10, so using it has been safe for a long while now. No need to be afraid of it anymore. :-) – RickN Nov 02 '21 at 09:42