1

I was trying to solve one problem for sometime, and did research on stack-overflow but cant seem to be able to find any solution that would actually help me in achieving the result that I need to come to. I'm trying to assign an array of objects inside of an array, but instead of getting a value I get "Promise".

async function groupsCollections() {
    mongo.connect(config.mongoURI, (err, client) => {
        if (err) {
            console.error(err)
            return
        }
        const testFolder = './groupCollections';
        let s = fs.readdirSync(testFolder)
        let combine = [];
        // going into each directory (Groups)
        s.forEach(file => {
            let tes = fs.readdirSync(`${testFolder}/${file}`)
            let ad = tes.map(el => {
                let see = readFileAsync(`${testFolder}/${file}/${el}`, { encoding: 'utf8' }).then((text) => {
                    let jsonFile = JSON.parse(text)
                    return jsonFile;
                })
                    .catch((err) => {
                        console.log('ERROR:', err);
                    });
                return see
            })
            combine.push({ groupName: file, collections: ad })
        })
    })
}

enter image description here

What should i change in my code, so that instead of Promises you would actually see values ? I was trying to solve this problem for hours but cant seem to find any other better solutions, so decided to come here and hope someone can guide me for the sake of a better solution to achieve the desired results.

Would really appreciate any assistance.

Liniaq
  • 87
  • 1
  • 6
  • yes, `ad` is an array of promises, as that is what you return from `tes.map` – Jaromanda X Jun 26 '19 at 04:12
  • This needs to be totally rewritten. You don't mix plain callbacks with promises. After your first plain callback, you have no ability to return a resolved value from the `async` function any more. Then, you do async stuff inside a loop and somehow expecting a result after the loop. On top of that you're using sync file I/O in some places too. This is all over the place. The place to start is to make or get promise version of every single asynchronous operation here and use promise chaining and `async/await` to make this a ton simpler. – jfriend00 Jun 26 '19 at 04:15
  • Also, you shouldn't use async function (`readFileAsync`) inside a sync function (`.map`). That's one of the reason you got `[Promise]` returned. – yqlim Jun 26 '19 at 04:17
  • I only understood that i need to rewrite it, can u give an example of how exactly and then i can just follow the lead? – Liniaq Jun 26 '19 at 04:18
  • You use the `async` keyword but never use `await`, you have a combination of synchronous and asynchronous file system calls, etc. But anyway, _THE_ reason you are getting an array of promises from you `.map()` call is because the return _to_ `.map()` is the variable `see` - which contains the promise from your call to `readFileAsync()`. Use `await` for that method. – Randy Casburn Jun 26 '19 at 04:21
  • Why is all this wrapped in a `mongo.connect()` callback? You never use `client`? – Randy Casburn Jun 26 '19 at 04:24
  • Change: `return see` To: `return await see` - that should do it (ignoring the rest of the structure). – Randy Casburn Jun 26 '19 at 04:29

2 Answers2

2

Rewritten to use async/await, untested

function groupsCollections() {
  return new Promise((resolve, reject) => {
    mongo.connect(config.mongoURI, (err, client) => {
      if (err) return reject(err)

      const testFolder = './groupCollections'
      let files = fs.readdirSync(testFolder)
      let combine = [];
      for (let i in files) {
        let tes = fs.readdirSync(`${testFolder}/${files[i]}`)
        let ad = tes.map(el => {
          try {
            return JSON.parse(fs.readFileSync(`${testFolder}/${files[i]}/${el}`, {
              encoding: 'utf8'
            })
          } catch (err) {
            console.log('ERROR:', err)
          }
        })
        combine.push({
          groupName: files[i], collections: ad
        })
      }
      resolve(combine)
    })
  })
}
Lawrence Cherone
  • 46,049
  • 7
  • 62
  • 106
1

To handle async function in map you need to add Promise.all:

async function groupsCollections() {
  mongo.connect(config.mongoURI, (err, client) => {
    if (err) {
      console.error(err);
      return;
  }
  const testFolder = "./groupCollections";
  let s = fs.readdirSync(testFolder);
  let combine = [];
  // going into each directory (Groups)
  s.forEach(async file => {
    let tes = fs.readdirSync(`${testFolder}/${file}`);
      let ad = await Promise.all(tes.map(el => readFileAsync(`${testFolder}/${file}/${el}`, {encoding: "utf8" })
        .then(text => JSON.parse(text))
        .catch(err =>  console.log("ERROR:", err)))
    );
    combine.push({ groupName: file, collections: ad });
  });
});

}

Ziv Ben-Or
  • 1,149
  • 6
  • 15
  • doesnt work, trying to console log, but doesnt really show anything, but thanks for the effort i appreciate it – Liniaq Jun 26 '19 at 06:30