こんにちは、さるまりんです。
これまで、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
について、もう少し見てみたいと思います。
読んでくださってありがとうございました。
それではまた!