JavaScriptのawaitってなに?Promiseの結果を待って受け取ってみよう

こんにちは、さるまりんです。

これまで、JavaScriptの非同期処理について少しずつ見てきました。

まずは Promise。

そして、Promiseが成功したときの結果を受け取る、

then()

失敗したときに使う、

catch()

について見てきました。

then()についての記事、catch()についての記事も、よければあわせてどうぞ。

今回は、その続きです。

JavaScriptには、

await

というものがあります。

英語の await には、

待つ

という意味があります。

では、JavaScriptでは何を待つのでしょうか。

今回は、Promiseの結果を await で待って受け取ってみます。

まずはPromiseを用意します

例えば、1秒後に、

できました!

という結果を返すPromiseを作ってみます。

const promise = new Promise((resolve) => {
    setTimeout(() => {
        resolve("できました!");
    }, 1000);
});

このPromiseは、すぐには結果を返しません。

1秒ほど待ってから、

resolve("できました!");

が実行されます。

then()ならこう受け取っていました

これまで見てきた then() を使うなら、

promise.then((result) => {
    console.log(result);
});

と書けます。

Promiseの結果が返ってきたあとに、

console.log(result);

が実行されます。

結果は、

できました!

です。

awaitを使って受け取ってみます

今度は、同じPromiseを await で受け取ってみます。

async function run() {
    const result = await promise;

    console.log(result);
}

run();

実行すると、1秒ほどあとに、

できました!

と表示されます。

then() を使ったときと同じ結果ですね。

awaitの次の行はすぐに動かないの?

ここが、少し不思議なところです。

const result = await promise;

console.log(result);

と書いてあると、

「console.log(result) はすぐに実行されないの?」

と思うかもしれません。

でも、すぐには実行されません。

await promise

のところで、Promiseの結果が返ってくるのを待ちます。

今回なら、

resolve("できました!");

が実行されるまで待ちます。

結果が返ってきたら、

result

に、

できました!

が入ります。

そのあとで、

console.log(result);

が実行されます。

つまり、

Promiseの結果を待つ
↓
resultに結果を入れる
↓
console.log(result)を実行する

という流れです。

resultにPromiseが入るわけではない

ここも大事なところです。

const result = await promise;

と書いたとき、result にPromiseそのものが入るわけではありません。

await は、Promiseの結果が返ってくるまで待って、

その結果を受け取ります。

今回なら、

promise

が最終的に、

できました!

という結果を返すので、

result

には、

できました!

が入ります。

だから、その次に、

console.log(result);

と書くと、

できました!

と表示されるんですね。

then()と比べてみましょう

then() を使う場合は、

promise.then((result) => {
    console.log(result);
});

でした。

Promiseの結果が返ってきたあとに、

console.log(result);

を実行しています。

一方、await を使うと、

const result = await promise;

console.log(result);

と書けます。

見た目は違いますが、どちらも、

Promiseの結果を待つ
↓
結果を受け取る
↓
そのあとの処理をする

という流れです。

then() では、

.then((result) => {

の中に続きを書いていました。

await では、

await promise

の次の行に続きを書けます。

そのため、上から順番に読みやすく感じることがあります。

本当に待っているのか見てみます

少しだけ表示を増やしてみます。

const promise = new Promise((resolve) => {
    setTimeout(() => {
        resolve("できました!");
    }, 1000);
});

async function run() {
    console.log("awaitの前");

    const result = await promise;

    console.log("awaitの後");
    console.log(result);
}

run();

実行すると、まず、

awaitの前

と表示されます。

そして1秒ほどあとに、

awaitの後
できました!

と表示されます。

つまり、

const result = await promise;

のところで、その関数の続きが一旦待っていることがわかります。

JavaScript全部が止まるわけではありません

では、await を使うとJavaScript全部が止まるのでしょうか。

そういうわけではありません。

例えば、

const promise = new Promise((resolve) => {
    setTimeout(() => {
        resolve("できました!");
    }, 1000);
});

async function run() {
    console.log("awaitの前");

    const result = await promise;

    console.log("awaitの後");
    console.log(result);
}

console.log("runを呼びます");

run();

console.log("runを呼びました");

とすると、まず、

runを呼びます
awaitの前
runを呼びました

と表示されます。

そして1秒ほどあとに、

awaitの後
できました!

と表示されます。

run() の中では、

await promise

のあとを待っています。

でも、その間にも、

console.log("runを呼びました");

は実行されています。

つまり、

awaitはJavaScript全部を止めるのではなく、そのasync関数の続きが結果を待つ

ということなんですね。

asyncは今回は少しだけ

ここまでのコードでは、

async function run() {

と書いています。

通常のJavaScriptでは、関数の中で await を使うときは async を付けます。

なので今回は、

awaitを使う関数にはasyncを付ける

くらいで大丈夫です。

async そのものにも、

「async関数は何を返すの?」

という大事な話があります。

そこはまた別の記事で、ゆっくり見てみましょう。

まとめ

今回は、JavaScriptの await を使って、Promiseの結果を待って受け取ってみました。

例えば、

const promise = new Promise((resolve) => {
    setTimeout(() => {
        resolve("できました!");
    }, 1000);
});

というPromiseがあったとき、

async function run() {
    const result = await promise;

    console.log(result);
}

run();

と書けます。

大事なのは、

const result = await promise;

のところです。

ここでは、

Promiseの結果を待つ
↓
結果が返ってくる
↓
resultに入れる
↓
次の行へ進む

という流れになっています。

だから、

console.log(result);

が先に動いてしまうことはありません。

await は、

Promiseの結果を待ってから、その続きへ進む

ための書き方です。

次は、

async

について、もう少し見てみたいと思います。

読んでくださってありがとうございました。

それではまた!