forEachでawaitを使おうとしたら怒られた

# はじめに
forEachでawaitを使おうとしたら、エラーになり、どうやったらループでawaitを使えるか調べたので、簡単に記載します。

# await とは？
awaitは非同期処理が終わるまで処理を止めておいてくれる便利なもの
jsはawaitやpromiseを使わないと、処理が終わる前に他の処理を実行してしまうので、直列に処理を実行したいときなどは利用すると良い

``` js
// 非同期関数
async function asyncTask(name) {
    console.log(`Task ${name} started.`);
    await new Promise(resolve => setTimeout(resolve, 2000)); // 2秒間スリープ
    console.log(`Task ${name} completed.`);
}

// メイン処理
async function main() {
    console.log("Main started.");

    // `await`を使って非同期処理を待つ
    await asyncTask("A");
    await asyncTask("B");

    // `asyncTask`を`await`なしで呼び出す
    asyncTask("C");
    asyncTask("D");

    console.log("Main completed.");
}

main();
```

```
Main started.
Task A started.
Task A completed.
Task B started.
Task B completed.
Task C started.
Task D started.
Main completed.
Task C completed. // このログが出る前にMain処理の最後のログ出力が実行されている
Task D completed.
```

# ループでawaitを使う
forEachでawaitを実行しようとしたが、うまく動作しなかった。
forEachは配列の各要素に対してコールバック関数を実行するものだが、コールバック関数でPromiseを返しても、その解決を待たずに次のコールバックが呼ばれるらしい

じゃあどうする？
## 解決策1 for of
``` js
async function asyncTask(name) {
    console.log(`Task ${name} started.`);
    await new Promise(resolve => setTimeout(resolve, 1000)); // 1秒待機
    console.log(`Task ${name} completed.`);
}

async function runForOf() {
    const tasks = ['A', 'B', 'C'];

    for (const task of tasks) {
        await asyncTask(task);
    }

    console.log('Finished processing with for...of');
}

runForOf();
```
## 解決策2 for
```js
async function asyncTask(name) {
    console.log(`Task ${name} started.`);
    await new Promise(resolve => setTimeout(resolve, 1000)); // 1秒待機
    console.log(`Task ${name} completed.`);
}

async function runFor() {
    const tasks = ['A', 'B', 'C'];

    for (let i = 0; i < tasks.length; i++) {
        await asyncTask(tasks[i]);
    }

    console.log('Finished processing with for');
}

runFor();

```
## 解決策3 Array.prototype.reduce()
```js
async function asyncTask(name) {
    console.log(`Task ${name} started.`);
    await new Promise(resolve => setTimeout(resolve, 1000)); // 1秒待機
    console.log(`Task ${name} completed.`);
}

async function runReduce() {
    const tasks = ['A', 'B', 'C'];

    await tasks.reduce(async (previousTask, currentTask) => {
        await previousTask;
        return asyncTask(currentTask);
    }, Promise.resolve());

    console.log('Finished processing with reduce');
}

runReduce();

```
## 解決策4 Array.prototype.map() & Promise.all()
```js
async function asyncTask(name) {
    console.log(`Task ${name} started.`);
    await new Promise(resolve => setTimeout(resolve, 1000)); // 1秒待機
    console.log(`Task ${name} completed.`);
}

async function runMap() {
    const tasks = ['A', 'B', 'C'];

    await Promise.all(tasks.map(task => asyncTask(task)));

    console.log('Finished processing with map and Promise.all');
}

runMap();

```
## 解決策5 for ループと非同期タスクの配列を使用
```js
async function asyncTask(name) {
    console.log(`Task ${name} started.`);
    await new Promise(resolve => setTimeout(resolve, 1000)); // 1秒待機
    console.log(`Task ${name} completed.`);
}

async function runTasks() {
    const tasks = ['A', 'B', 'C'];
    const promises = [];

    for (const task of tasks) {
        promises.push(asyncTask(task));
    }

    await Promise.all(promises);

    console.log('Finished processing with for loop and Promise.all');
}

runTasks();

```