使用回调

时间:2017-03-14 00:47:41

标签: javascript node.js asynchronous ecmascript-6 promise

我的头衔很糟糕。让我详细说明一下:

我正在使用节点7.2.0和Electron。我有一组Song个对象,其中一个键叫filepath。我需要为每首歌按顺序执行以下操作:

  1. 获取他们的ID3元数据
  2. 将艺术家和曲目信息发送到API
  3. 将API中的正确曲目信息应用于每个对象
  4. 分类到专辑
  5. 显示结果
  6. 所以我需要知道的是:链接异步函数的最佳方法是什么,以及如何在链完成时实现回调。

    我应该尽快通过所有步骤运行每个song吗?我应该等到所有歌曲都完成第1步,然后转到第2步,然后在第3步完成所有第2步,等等。

    其次,当所有上述步骤(可能在forEach循环中)完成时,运行回调的可接受方式是什么?我应该使用节点async库还是承诺?我一直在读,我应该在承诺中包含每个单一函数,然后使用Promise.all()来运行回调,但我不确定它是否是最新的。

    编辑:代码示例。它并不多,但它只是我拥有的一切。在我潜入太远之前,我决定问这个问题,后悔我的选择。

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

1 个答案:

答案 0 :(得分:1)

概述您可以使用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
});