0

I'm using node's readdir to asynchronously read the content of a directory then parse it with music-metadata. From the metadata, I want to extract artist and title info, and return it as json. Here's my code:

router.get('/library/', (req, res) => {
  const collection = process.cwd() + '/music/'
  let library = {
    songs: [],
  }

  fs.readdir(collection, (err, files) => {
    if (err) throw err
    files.forEach(async file => {
      let song = {
        artist: '',
        title: '',
      }
      let resopnse = await mm.parseFile(collection + file)
      song.artist = resopnse.common.albumartist
      song.title = resopnse.common.title
      library.songs.push(song)
    })
    console.log(library) // why this is empty
  })

  res.json({ message: `${library}` })
})

The library object returned by the above is empty. I thought that I'm awaiting in all the right places? What did I miss?

boojum
  • 574
  • 6
  • 19
  • `forEach` doesn't `await` the promise returned by the anonymous function you pass to it, and isn't async itself. – Quentin Apr 09 '20 at 13:52
  • You're also trying to use `library` outside the asynchronous `readdir` function (which isn't async so you can't await it). – Quentin Apr 09 '20 at 13:57
  • node documentation says that `readdir` is asynchronous..? Here: https://nodejs.org/api/fs.html#fs_fs_readdir_path_options_callback – boojum Apr 09 '20 at 15:47
  • Also, `library` is defined outside of the functions - shouldn't `library.songs.push(song)` update it? Apologise my ignorance, I'm merely a learner ;-) – boojum Apr 09 '20 at 15:51
  • It *will* update `library` … you just return it before that happens. – Quentin Apr 09 '20 at 15:55
  • Also note the difference between being asynchronous and the use of the `async` keyword / returning a promise which make something asynchronous **and** conform to a particular API for resolving that (and API which didn't exist when the `fs` module was designed) – Quentin Apr 09 '20 at 15:57
  • Thanks for clarifying `async` and `readdir`! I get the difference now. But... "you just return it before that happens" confuses the hell out of me. I thought that I was awaiting for all the necessary things..? Heh, I might have to read more about `async` / `await`. Thanks! – boojum Apr 09 '20 at 16:05
  • "I thought that I was awaiting for all the necessary things..?"— No. See my very first comment, and the duplicate question. – Quentin Apr 09 '20 at 16:06
  • I did, and changed `forEach` to `for await (const file of files)` but it didn't help. Either way, those comments are getting a bit verbose for a closed question. I will do some more digging and if I can't figure it out then will ask another question. – boojum Apr 09 '20 at 16:10
  • The duplicate has examples of how to use a `for` loop with `await` – Quentin Apr 09 '20 at 16:13

0 Answers0