WEB

【JavaScript】プロミスチェーンをArray.reduceで処理する方法

WEB
この記事は約2分で読めます。

はじめに

配列をループしながら、順番に非同期処理を行いたい…

単純にforでループすればなんのことはないのですが、Arrayメソッドでもぜひやってみたい…

要求

  • 音声ファイルが配列に入っている
  • 再生のためのaudioPlay()メソッドはPromiseを返す
  • 音声ファイルを再生し、終わったら自動で次のトラックへ
  • 最後まで再生したら、終了する

音声データ

const audioDatas = [
  'https://otologic.jp/sounds/jing/pre/mei%20kara%20mei%20switch1.mp3',
  'https://otologic.jp/sounds/jing/pre/pastel%20color1.mp3',
  'https://otologic.jp/sounds/jing/pre/yattaze!2.mp3',
  'https://otologic.jp/sounds/jing/pre/birdland1.mp3',
  'https://otologic.jp/sounds/jing/pre/tumazuku%20kanzi1.mp3',
];

失敗

forEachはうまくいきませんでした。
コールバックのawaitは機能しません。

失敗

audioDatas.forEach(async (data) => await audioPlay(data));

// すべての音声が一気に再生されてしまう

実装

Array.reduceを使って、以下のようにしてみました。

成功

audioDatas.reduce((p, data) => p.then(() => audioPlay(data)), Promise.resolve());

内容

  • reduceの初期値はPromice.resolve() -> つまりPromise
  • audioPlay()の返りPromisepに入っていく
  • トラックの再生が終わるとp.then()のコールバックが動く
  • 以下ループ…

まとめ

もっといいやり方があれば教えて欲しいです。