今回は前回に引き続き、非同期処理について書いていきたいと思います。今回はPromiseのシンタックスシュガーであるasync awaitです。これを使うと簡単に非同期処理を制御することができ、現在のJavaScriptで必須の知識になっているのでしっかり見ていきます。
thenを使って書いてみる
まずは、thenで受け止める書き方について見ていきます。今回もサンプルコードはりあクト!から拝借しています。
import fetch from 'node-fetch';
const getUser = async (userId) => {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`)
if (!response.ok) {
throw new Error(`${response.status} Error`);
} else {
return response.json();
}
}
console.log('-- Start --');
getUser(2)
.then((user) => {
console.log(user);
})
.catch((error) => {
console.log(error);
})
.finally(() => {
console.log('-- Completed --');
});
さっそくasync awaitが使われていますが、一旦この部分は気にしないことにします。重要なのはgetUser()を実行することで、Promiseオブジェクト(以下Promise)が変えるということです。それでは、詳しく追っていきます。
まず、4行目ではAPIを叩いて、データを得ます。ここでは、Responseオブジェクトが返り変数responseに代入されます。
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`)
Responseオブジェクトは色々なプロパティやメソッドを持っており、その中のひとつのResponse.okというプロパティを使います。これは、ステータスコードが200ならtrueを返し、それ以外ならfalseを返すというものです。
少しややこしいですが、!が使われているので、ステータスコード200が返ると9行目が実行されます。これもResponseオブジェクトが持つメソッドのひとつで、取得したデータをPromiseオブジェクトで返してくれます。
return response.json(); // ユーザデータがPromiseオブジェクトで返る
そのため、15行目のgetUser(2)の返り値はPromiseになります。Promiseが返っているので、then()で受け止めることができます。thenの引数のuserには先程returnしたユーザのデータが入っているので、これを実行すると、次のようになります。
$ node get-user-then.js
-- Start --
{
id: 2,
name: 'Ervin Howell',
username: 'Antonette',
email: 'Shanna@melissa.tv',
address: {
street: 'Victor Plains',
suite: 'Suite 879',
city: 'Wisokyburgh',
zipcode: '90566-7771',
geo: { lat: '-43.9509', lng: '-34.4618' }
},
phone: '010-692-6593 x09125',
website: 'anastasia.net',
company: {
name: 'Deckow-Crist',
catchPhrase: 'Proactive didactic contingency',
bs: 'synergize scalable supply-chains'
}
}
-- Completed --
ここで、何度も登場したResponseオブジェクトの詳細はMDNのページに詳細が乗っています。一度目を通しておくといいかと思います!
async awaitを使う場合
さて、次にasync awaitを使うとどのように書けるのかを見ていきます。
import fetch from 'node-fetch';
const getUser = async (userId) => {
const response = await fetch(
`https://jsonplaceholder.typicode.com/users/${userId}`,
);
if (!response.ok) {
throw new Error(`${response.status} Error`);
}
return response.json();
};
console.log('-- Start --');
const main = async () => {
try {
const user = await getUser(2);
console.log(user);
} catch (error) {
console.error(error);
} finally {
console.log('-- Completed --');
}
};
main();
17行目までは先程と同じです。17行目にはasyncという何やら見慣れないものがでてきました。これはこの先説明するawaitを使うために必要なものです。ルールとして引数の前にasyncを書きます。
const main = async () => { // 非同期処理をawaitで制御する場合は、asyncをつける
ここで、userという変数に取得したユーザ情報を代入しているのですが、その前にawaitがついています。日本語で「待つ」という意味の通り非同期処理でありながら、getUser(2)が完了するまで、次の処理に移るのを待ちます。非同期処理は通常、並列で実行が可能なのでユーザの取得に遅れようものなら、待たずに次へ進んでしまいます。すると、userがundefinedになるので、途中でエラーになります。それを防ぐためthenを使って制御しているのでした。それをawaitと書くだけで、userという変数に値が入っていることが担保されるわけです。すごく便利ですね!
実行してみると問題なくユーザが取得できていることが確認できると思います。
$ node get-user-await.js
-- Start --
{
id: 2,
name: 'Ervin Howell',
username: 'Antonette',
email: 'Shanna@melissa.tv',
address: {
street: 'Victor Plains',
suite: 'Suite 879',
city: 'Wisokyburgh',
zipcode: '90566-7771',
geo: { lat: '-43.9509', lng: '-34.4618' }
},
phone: '010-692-6593 x09125',
website: 'anastasia.net',
company: {
name: 'Deckow-Crist',
catchPhrase: 'Proactive didactic contingency',
bs: 'synergize scalable supply-chains'
}
}
-- Completed --
さいごに
今回はReactでの開発でもよく使われているasync awaitについて見てきました。何となく使うこともできるけど、基本であるPromiseの理解をしておくのはやっぱり大事だと感じました。(何より気持ち悪い…)
ここまで読んでいただきありがとうございました。