Kieran E
Kieran E

Reputation: 3666

Correct way to chain multiple async functions on array items with callback

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.
});

Upvotes: 0

Views: 942

Answers (1)

Jaromanda X
Jaromanda X

Reputation: 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
});

Upvotes: 1

Related Questions