0

My title is kind of gross. Let me elaborate:

I'm using node 7.2.0 and Electron. I have an array of Song objects with a key called filepath. I need to do the following for each song, in order:

  1. Get their ID3 metadata
  2. Send artist and track info to API
  3. Apply correct track information from API to each object
  4. Sort into albums
  5. Display results

So what I need to know is this: what is the best way to chain aync functions, and how can I implement a callback when the chain completes.

Should I run each song through all the steps as soon as I can? Should I wait until all songs are done step 1, then move to step 2, then step 3 when all are finished step 2, etc.

Secondly, what's the accepted way to run a callback when all the above steps (probably in a forEach loop) finish? Should I use the node async library or promises? I've been reading that I should wrap each singular function in a promise then use Promise.all() to run a callback, but I'm not sure if that's up to date.

Edit: Code example. It's not much, but it's all I have. I decided to ask this before I dive too far in and regret my choice.

let songs = SongHelpers.createSongArray(MUSIC_DIR);
songs.forEach((song) => {
// I'm putting the contents of the applyMetadata function here to ease readability for this question
// SongHelpers.applyMetadata(song, callback);

  // mm is from the musicmetadata package: https://github.com/leetreveil/musicmetadata
  mm(fs.createReadStream(song.filepath), function (err, metadata) {
    try {
      if (err) throw (err);
      return metadata;
    } catch (e) {
      console.error(`Error in mm parsing: ${e.message}`);
    }
  });
  // Then send to API
  // Then apply API response to each track
  // etc.
});
7
  • 1
    You should use Promise.all if you want to attach a callback to resolve when all contained promises have resolved. If you want each promise to run a callback as soon as it has individually resolved, attach each then individually - probably using map not forEach (that way you can pass the array of mapped promises to Promise.all). If you can give some basic example of what your code looks like it would be helpful. Commented Mar 14, 2017 at 0:59
  • 1
    use Promises or asyncjs - not both Commented Mar 14, 2017 at 1:01
  • @Damon I added an example, but keep in mind it's not a full implementation. I decided to ask this question before I proceed so that I don't regret my choice later. Commented Mar 14, 2017 at 1:05
  • what does mm do? Commented Mar 14, 2017 at 1:09
  • @JaromandaX, my bad. It's this library for ID3 parsing: github.com/leetreveil/musicmetadata Commented Mar 14, 2017 at 1:11

1 Answer 1

1

An overview of what you can do with Promises

let songs = SongHelpers.createSongArray(MUSIC_DIR);
Promise.all(songs.map(song => new Promise((resolve, reject) => {
    mm(fs.createReadStream(song.filepath), function (err, metadata) {
        if (err) {
            return reject(err);
        }
        resolve(metadata);
    })).then(metadata => {
        // Send artist and track info to API, 
        // should return a Promise that resolves when the API returns a result
    }).then(result => {
        // apply correct track information, return some value that could be used in the sort step
    });
})).then(results => {
    // results is an array of values returned in the last step above
    // sort and display here
}).catch(err => {
    // handle error here
});
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.