⏳
Promiseから学ぶasync/awaitと、並列処理 Promise.all
モダンなフロントエンド開発において、API との通信(非同期処理)は避けて通れない業務。
今回は async/await 以前の Promise から理解してまとめていきたいと思います。
1. async/await に行く前に。全ての基礎「Promise」の書き方
async 以前はPromise オブジェクトを使い、.then() で処理をつなげていました。
async/await があるから今は覚えなくてよさそう、とも思いますが Promise の構造を知っておいた方がいいと思うので記載しました。
// Promiseの基本
const myFirstPromise = () => {
return new Promise((resolve, reject) => {
const success = true;
if (success) {
resolve("データを取得しました!");
} else {
reject("失敗しました...");
}
});
};
// 実際に使うときはPromiseチェーン
// 東京(緯度:35.67, 経度:139.65)の現在の天気を例として取得
const url =
"https://api.open-meteo.com/v1/forecast?latitude=35.67&longitude=139.65¤t_weather=true";
console.log("通信開始...");
fetch(url) // fetch()関数でデータurlを取得
.then((response) => {
// 受け取ったデータがおかしい・なければエラーを出す
if (!response.ok) {
throw new Error("ネットワークエラーが発生しました");
}
// OKであればデータをjsonにして出力して次のステップへ
return response.json(); // ここでまたPromiseが返る(解析待ち)
})
.then((data) => {
// jsonデータができたらこのステップに移動する
console.log("取得成功!", data.current_weather);
console.log(`現在の気温は ${data.current_weather.temperature}度 です。`);
})
// jsonデータがあってもdata.current_weatherなどのデータがなかったらエラーを出す
.catch((error) => {
console.error("エラーが発生しました:", error);
})
// 一番最後に出力する
.finally(() => {
console.log("通信処理を終了します。");
});
わかりにくくはないけどチェーンが目に付く感じです。
2. async/await で書き換える場合
async を使うとチェーンもなくなりすっきりしたコードになります。
const getWeather = async () => {
const url =
"https://api.open-meteo.com/v1/forecast?latitude=35.67&longitude=139.65¤t_weather=true";
try {
console.log("通信開始...");
const response = await fetch(url);
if (!response.ok) throw new Error("取得に失敗しました");
const data = await response.json();
console.log(`現在の気温は ${data.current_weather.temperature}度 です。`);
} catch (error) {
console.error("データを受信できませんでした。", error);
} finally {
console.log("処理終了");
}
};
getWeather();
3. パフォーマンスを最大化する「Promise.all」
「ユーザー情報」と「投稿一覧」を両方取得する場合など、それぞれのデータ取得に順序建てが必要ない場合は Promise.all を使うことで並列処理が可能です。
// 悪い例(直列処理):1つ目が終わるまで2つ目が始まらない
const user = await fetchUser(); // 1秒かかる
const posts = await fetchPosts(); // 1秒かかる
// 合計 2秒
// 良い例(並列処理):同時にリクエストを送る
const [user, posts] = await Promise.all([fetchUser(), fetchPosts()]);
// 同時に処理するので1秒で済む
4. React ではこんな感じの記載に
非同期処理は、常に「3 つの状態」とセットで設計する必要があります。
- Loading(読み込み中):ぐるぐるを表示する
- Success(成功):データを表示する
- Error(失敗):エラーメッセージを出す
const [loading, setLoading] = useState(false);
const handleAction = async () => {
console.log("データを取得します。しばらくお待ちください。");
setLoading(true); // 開始
try {
await someApiCall();
} catch (error) {
console.error("データを受信できませんでした。", error);
} finally {
setLoading(false);
console.log("処理を終了いたします。");
}
};
まとめ:安全に処理し、エラー・終わりまで記載してエンジニアにもユーザーにもわかりやすく
非同期処理を丁寧に書くことは、そのままユーザーへの優しさに繋がります。
通信エラーで画面が固まらないようにする
Promise.all で待ち時間を最小にする
適切なエラーメッセージでユーザーを迷わせない
「動けばいい」だけでなく 「わかりやすい」 コードを書いていきたいと思います。
Discussion