225
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Organization

僕でもわかるasync/await

サルでも分かるで挫折し、ミジンコでも分かるで挫折したわたしに。

サル > ミジンコ > 僕

僕でも分かるasync/awaitまとめました。
モダンブラウザで動きます。Developer Toolのコンソールで試してみてください。
(本記事のサンプルはgoogle.comドメインのページでお試しください。googleさんお邪魔します)

fetch APIで試す

ブラウザからAjaxリクエストなどに使えるfetch APIで試します。

jQueryなどのAjax通信を思い出すと、レスポンスを取得した際のロジックはコールバック関数で定義しますね。fetchを使うと以下のように同期処理っぽく書けます。

(async () => {
    const response = await fetch("https://www.google.com")
    const html = await response.text()
    console.log(new DOMParser().parseFromString(html, "text/html").title)
})()
実行結果
Google

awaitで呼び出すのはasyncで定義された関数です。
また、awaitはasyncで定義された関数の中で使う必要があります。
トップレベルなどで使うには上記のように無名関数で囲います。
(Chrome DevToolsのコンソールではasyncの無名関数が省略できます。便利。)

async function hoge() {
    await ...
}

(async () => {
    await hoge()
})()

ちなみにエラー処理はこんな感じ。

(async () => {
    try {
        const response = await fetch("https://not_exists_domain")
    } catch (error) {
        console.log(error)
    }
})()

ループ処理で使う

forEachで使う

forEachなどのコレクション用の関数内で利用するときは注意が必要です。
以下は構文エラーにはなりませんが、1週目と2週目が同時に実行されてしまいます。
しかもawait処理の終了を待ってくれません。


(async () => {
    ["https://www.google.com", "https://www.google.com/doodles/"].forEach(async (url) => {
        const response = await fetch(url)
        const html = await response.text()
        console.log(new DOMParser().parseFromString(html, "text/html").title)
    })
    console.log("finish")
})()
実行結果
finish
Google
Doodle

順次実行する

順番に実行するためにはforやfor-ofなどを使います。

(async () => {
    for (const url of ["https://www.google.com", "https://www.google.com/doodles/"]) {
        const response = await fetch(url)
        const html = await response.text()
        console.log(new DOMParser().parseFromString(html, "text/html").title)
    }
    console.log("finish")
})()
実行結果
Google
Doodle
finish

並列実行で全部終わるのを待つ

forEachをmapに変えてPromise.allを使います。

(async () => {
    const results = await Promise.all(
        ["https://www.google.com", "https://www.google.com/doodles/"].map(async (url) => {
            const response = await fetch(url)
            const html = await response.text()
            return new DOMParser().parseFromString(html, "text/html").title
        })
    )
    console.log(results)
    console.log("finish")
})()
実行結果
["Google", "Doodle"]
finish

まとめ

Promise.allが使えるのはasync/awaitの実体がPromiseだからですね。
async/awaitの入門記事にはPromiseから入るものが多く難しい印象でしたが、とりあえず使うためには本記事の理解くらいでもいいのかなーと思って書きました。

使い慣れてきたらPromiseの理解を深めていきましょう!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
225
Help us understand the problem. What are the problem?