はじめに
配列をループしながら、順番に非同期処理を行いたい…
単純に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()
の返りPromise
がp
に入っていく- トラックの再生が終わると
p.then()
のコールバックが動く - 以下ループ…
まとめ
もっといいやり方があれば教えて欲しいです。