async/awaitを利用したコードの実行順序を把握したい！

はじめまして！！ノベルワークス2年目、駆け出しエンジニアのそうま([@SomaActionPlan](https://x.com/SomaActionPlan))です！！

今回は `async/await` を利用したコードの実行順序について整理しました！

# 調査理由
`async/await` を使って呼び出した関数内でもさらに `async/await` を使用している場合、コードの実行順序を頭で整理出来なくなってしまったため、今一度纏めようと思いました！！

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/async_function

# パターン1
呼び出した関数内で `async/await` を使用しなかった場合。

以下サンプルコードです。

```ts:sample.ts
const getSampleData = async(type: "users" | "comments") => {
    const response = await fetch(`https://jsonplaceholder.typicode.com/${type}`)
    return await response.json();
}

const request = async() => {
    // データ取得が完了したら、ログを出力
    getSampleData("users").then(() => {
        console.log("ユーザーデータ取得完了")
    })
    // データ取得が完了したら、ログを出力
    getSampleData("comments").then(() => {
        console.log("コメントデータ取得完了")
    })
}

const run = async() => {
    await request()
    console.log("通過")
}

run()
```

この場合ログの出力順はどうなるでしょうか？

僕は「`run` 関数内で `await` を使用しているんだし "通過" のログが一番最後に出る筈」だと思ってしまってました...。

しかし実際には以下のような順番になります！

1. "通過" のログ出力
2. "ユーザーデータ取得完了"のログ出力
3. "コメントデータ取得完了"のログ出力

当たり前っちゃ当たり前なんですが...確かに `run` 関数内で `await` を使用して `request` 関数を呼び出してはいますが、`request` 関数内の処理はレスポンスを待ちません。(正確には `json` のパース)

つまり、`request` 関数内の `getSampleData` の返す `Promise` が `pending`(待機中) の状態で、`request` 関数の返す `Promise` が `fulfilled`(履行済み) になってしまうので "通過" のログ出力が先に実行されると解釈しています！

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise

# パターン2

呼び出した関数内で 一部 `async/await` を使用した場合。

以下サンプルコードです。
(`request` 関数の最初の `getSampleData` の呼び出しに `await` を付けました)

```ts:sample.ts
const getSampleData = async(type: "users" | "comments") => {
    const response = await fetch(`https://jsonplaceholder.typicode.com/${type}`)
    return await response.json();
}

const request = async() => {
    // データ取得が完了したら、ログを出力
    await getSampleData("users").then(() => {
        console.log("ユーザーデータ取得完了")
    })
    // データ取得が完了したら、ログを出力
    getSampleData("comments").then(() => {
        console.log("コメントデータ取得完了")
    })
}

const run = async() => {
    await request()
    console.log("通過")
}

run()
```

この場合はどうなるでしょうか？

...そうですね！`request` 関数は最初の `getSampleData` 関数のレスポンスを待つので以下のような実行順になります！

1. "ユーザーデータ取得完了"のログ出力
2. "通過" のログ出力
3. "コメントデータ取得完了"のログ出力

# パターン3

今ままでを踏まえて、以下のようなコードの時実行順はどうなるか考えてみましょう。

```ts:sample.ts
const getSampleData = async(type: "users" | "comments" | "posts") => {
    const response = await fetch(`https://jsonplaceholder.typicode.com/${type}`)
    return await response.json();
}

const request = async() => {
    await getSampleData("users").then(() => {
        console.log("ユーザーデータ取得完了")
    })
    await getSampleData("comments").then(() => {
        console.log("コメントデータ取得完了")
    })
}

const postRequest = async() => {
    await getSampleData("posts").then(() => {
        console.log("ポスト完了")
    })
}

const run = async() => {
    postRequest()
    request()
}

run()
```

この場合は `request` 関数内の処理はコードの記載順に実行されますが、`postRequest` 内の処理と `request` 関数内の処理は並列実行となります。つまり、**"ユーザーデータ取得完了"ログ** と **"コメントデータ取得完了"ログ** は順番通りに出力されますが、**"ポスト完了"ログ** だけはどこで出力されるかわからない状態となります！！

![頭整理.drawio (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1100170/87251d58-b3e8-d4a0-b321-077bc6745b2a.png)

# 纏め
なんとなく`async/await` を用いた非同期処理の実行順について理解を深められたかなと思います！

ただ、以下でも書いたんですが、やはり `javascript` で書いたコードがブラウザでどういう仕組みで動いているのかを理解したいので、次回こそは「イベントループ」や「マイクロタスク」あたりの調査を進めていきたいです！

https://qiita.com/sato-souma/items/1ff431aab2d27c21523b