CSVの上から順に実行する必要
と聞くと
(A) 非同期処理の起動順序を「1番目が完了してから2番目を開始・・・」としなければならない
(B) 各々の非同期処理の結果が順番に並んでいさえすれば処理そのものは並行して行ってもかまわない
のうち(A)であるように思えますが、実は(B)である可能性もあるような気もします。もし(B)ならturbgraphics200さんの回答のように結果の順序にさえ配慮すれば解決できると思いました。
一方もし(A)ならばPromise.allは使えず、もう一工夫する必要があろうかと思います。Promiseを使う前提で考えるなら・・・
###thenチェーン
javascript
1
2const addresses = [ 'a', 'b', 'c', 'd' ]
3
4function submit(address) {
5 return new Promise((resolve, reject) => {
6 ...
7 });
8}
9
10addresses.reduce(
11 (p, address) => p.then(() => submit(address)),
12 Promise.resolve('dummy'));
thenチェーンを使うとsubmitは直前の仕事が完了してから起動されます。しかし、「何要素あるか」を意識できてその数だけthenを並べるなら見やすいですが、非同期処理の数が可変個数の場合は上記のようにreduceなどでthenチェーンを生成してやる必要がありそうです。
###async/await
async/awaitを使うと可変個数の非同期処理をawitしながらあたかも同期的に動かしているかのよう(に見える)書き方ができます。(ただ内部の動作はそう単純でもないところに注意が必要ですが)
Javascript
1async function submit(address) {
2 return new Promise((resolve, reject) => {
3 ...
4 });
5}
6
7async fuction submit_serial(addresses) {
8 for (let address of addresses) {
9 await submit(address); // 非同期処理の完了を待つ
10 }
11 console.log('全部のアドレス処理が完了するとここを通過します'); // (B)
12}
13
14const addresses = [ 'a', 'b', 'c', 'd' ]
15submit_serial(addresses);
16// これ以降はsubmit_serialとは並行して動いてしまうことに注意...
17console.log('ここでは非同期処理がまだおわってないです...'); // (A)
(A)ではまだ非同期処理が完了しておらず(B)が完了したときに通過する箇所になる点が注意点です。またsubmit_serialではfor文を使っておりforEach/mapを単純に使えない点にも注意が必要です。
addresses.forEach(async a => await submit(a));
のように書くと順番に実行されるのかなと思ってしまいますが、実際はそうなりません。forEach関数はasync関数ではないので引数にasync関数async a => await submit(a)
を渡してみてもforEachの方でそれをawaitしてくれません(当然といえば当然でした)。結果としてPromise.allと同じような動き(全ての非同期処理が同時にスタート)にしかなりません。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。