0
0

Array.mapの中でasync/awaitを使う

Last updated at Posted at 2024-07-26

はじめに

諸事情につき、Array.mapの中でasync/awaitを利用したのですが、思った以上に詰まった・・。
ということでメモがてら残しておきましょう。

参照(というかほとんど切り抜き元):

やりたかったこと

Arrayに入っている値を元に非同期関数を呼び出しつつ、その結果の値を整形した配列を用意する。
(最終的にjoinするだけで画面に表示したい)

イメージ図
dataArray:['1', '2', '3']
  ↓
result:['・りんご', '・みかん', '・いちご']
  ↓
画面
・りんご
・みかん
・いちご

結論

sample.js
const dataArray = ['1', '2', '3'];

const result = await Promise.all(dataArray.map(async (data) => 
    '' + await sampleFunction(data)
));

説明

dataArray.map(async (data) => await sampleFunction(data))

ここはまあ、見たまんまの動きです。
非同期関数を同期的に呼びたいので、無名関数の頭にasyncを付け、実際に呼び出す関数にはawaitを付けています。

こうすることで、dataArray.mapは無事同期的に結果を取得できる・・と思いきや、dataArray.mapにはawaitがついていないので、この無名関数の処理終了を待ちません。

コードを分解すると、こんな感じ。

// この関数内ではきちんと同期処理化している
async mapFunction(data) {
    return '' + await sampleFunction(data);
}

let result = [];
for (const data of dataArray) {
    result.push(mapFunction(data)); // こっち側が同期処理化していない
}

// そのため、Promiseの配列になってしまう
console.log(result); // [object Promise, object Promise, object Promise]

じゃあawait dataArray.mapとしたら良いのでは?と思ったのですが・・。
awaitPromiseが返される関数にのみ適用されるため、「Promiseの配列」だと無力です。
※エラーにもならなかった。

await Promise.all

ということで、Promise.allを使います。
こうすることで、配列内のPromiseが全て履行されてから次へ進むようになります。

解決!!

ちなみに・・

今回のパターンの場合、こっちでもできる。

sample2.js
const dataArray = ['1', '2', '3'];

const promiseResult = await Promise.all(dataArray.map(data => 
    sampleFunction(data)
));
const result = promiseResult.map(elem =>
    '' + elem
);

おそらく処理速度はほぼ一緒になる・・と思う・・・。
mapを2回呼び出している分だけロスがある??と思う???
(逆にasync/awaitの数が少ない分早かったりする??多分変わらないよね・・?)

さらにちなみに・・

await Promise.all(...).join('\n');

の書き方は許されませんでした。
多分Promise.all(...).join('\n')を評価した後にawaitをする流れになるから。

下記のどちらかにしましょう。

// パターン1
(await Promise.all(...)).join('\n');

// パターン2
const promiseResult = await Promise.all(...);
const result = promiseResult.join('\n');

おわりに

JavaScriptは奥が深いけど、なんとなく好きです。
自由度が高い・・気がする・・・。

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0