非同期処理 async/await
投稿日: 2025年02月22日
今回復習として、非同期処理について軽く書こうと思っています!
間違っていたらコメントいただけると嬉しいです😎
非同期処理というのは、処理が終わるのを待たずに、次の処理を進めることができる。
同期処理は、順番通りに実行され、前の処理が終わるまで次の処理が待機する。
よくある非同期処理の使い方の例
API通信(fetch, axios など)
データベースとのやり取り
ファイルの読み込み(画像、動画)
タイマー(setTimeout
, setInterval
)
ユーザーの操作待ち(クリック、スクロールなど)
WebSocket(リアルタイム通信)
画像のアップロード
非同期的な計算(Web Workers)
ShiftBでよく使われるのは、API通信や画像のアップロードやユーザーの操作待ち(クリック、スクロールなど)?とかですかね。
実行の流れ
同期処理 は、コードが 上から順番に 実行される。
→ 前の処理が終わらないと、次の処理に進まない。
非同期処理 は、処理が並行して実行されることがある。
→ 処理を待たずに、次の処理に進むことができる。
処理の待ち時間
同期処理 は、 前の処理が完全に終わるまで、次の処理は実行されない。
→ 例えば、計算処理の結果が出るまで待つ必要がある。
非同期処理 は、 処理が終わるのを待たずに、他の処理を進めることができる。
→ 必要なら await
を使って、一時的に処理を待つことも可能。
API通信・データベースアクセス
同期処理 では、APIのレスポンスが返るまで プログラム全体がストップ する。
→ この間、ユーザーが画面操作できなくなる可能性もある。
非同期処理 では、 APIのレスポンスを待つ間に、他の処理を進めることができる。
→ UIの動作を止めずに、スムーズな処理ができる。
以下のコードでは、API通信の使い方で、フロント側がAPIへリクエストし、データを取得しています!
もし、正しく取得できない場合は、型やデータ構造が API側と合っていないので
API側に合わせる必要があります。await
を使って、APIからのレスポンスを待って処理を進める。(ここポイント!!)
ここで処理を一時的に待たないと、レスポンスがまだ届いていない(データが無い)のまま、次の処理進めることになってしまう。
const response = await fetch("/api/admin/cafe_submission_form", { method: "GET",
headers: { "Content-Type": "application/json",
Authorization: Bearer ${token},
},
});
2.正しく取得できたら、今度はそれをJSON形式に変換する必要があります。
APIから「テキストデータ」として送られてくるので、テキストデータのままだと扱いにくい状態です。
なので、フロント側ではそのテキストデータをJSON形式にする必要があります。
if (response.ok) { const data = await response.json(); // 📝 受け取ったデータを JSON に変換
取得したデータを formState
に保存して、反映させる。
if (data.cafe) {
setFormState(data.cafe); // 🔄 フォームの初期値としてセット
}
以下、コード
//フロント側
// GETメソッド(カフェ投稿フォームの情報取得)
useEffect(() => {
if (!token) return;//未ログインの場合は、API送らない
const fetchData = async () => {
try {
const response = await fetch("/api/admin/cafe_submission_form", {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
});
if (response.ok) {
const data = await response.json();
if (data.cafe) {
setFormState(data.cafe);
}
}
} catch (error) {
console.error("Failed to fetch cafe data:", error);
}
};
fetchData();
}, [token]);//依存配列にtoken設定することで、ログインユーザ-のみデータを取得できる
//バックエンド側(API)
export const GET = async (request: NextRequest) => {
const { currentUser, error } = await getCurrentUser(request);
if (error || !currentUser || !currentUser.user) {
return NextResponse.json({ message: "Unauthorized" }, { status: 400 });
}
try {
const user = await prisma.users.findUnique({
where: { supabaseUserId: currentUser.user.id }, // Int型に変換したuserIdを使う
include: {
cafes: {
select: {
id: true,
cafeName: true,
thumbnailImage: true,
createdAt: true, // 新しいカフェ順に並べる
},
orderBy: {
createdAt: "desc",
},
},
favorites: {
include: {
cafe: {
select: {
id: true,
cafeName: true,
starRating: true,
locationCoordinates: true,
},
},
},
},
information: {
select: {
latestInfo: true,
recommended_cafe: true,
recommendation_reason: true,
},
},
},
});
if (!user) {
return NextResponse.json(
{ status: "Not Found", message: "ユーザー情報が見つかりません" },
{ status: 400 }
);
}
return NextResponse.json({ status: "OK", user }, { status: 200 });
} catch (error) {
if (error instanceof Error) {
return NextResponse.json({ status: error.message }, { status: 400 });
}
}
};
JSONとは、JavaScriptでデータを扱いやすくするデータ構造。
具体的な処理の流れは、以下の通りとなります。
1. GETメソッドで、APIへカフェ投稿フォームの情報をリクエストする
2. APIからのレスポンスをGETして、カフェ投稿フォームを取得する
3. 取得したカフェ投稿フォームをJSON形式に変換し、扱いやすいデータにする
4. うまくデータを取得できなかったら、非同期処理のエラーハンドリングを出力する。問題なかったらスルー
5. 依存配列に token
を設定することで、ユーザーがログイン状態だったらカフェ情報フォームが取得でき、未ログインだったら取得できないようにしている。
余談ですが、useEffect の依存配列のtokenについて。
useEffect の依存配列 [token]
によって token
が変わるたびに処理が実行されるが、if (!token) return;
によって未ログイン時は処理をスキップします。
これにより、ログインしているユーザーのみデータを取得できるようになっています。
useEffectと依存配列についての記事は、以下のリンクとなります。
https://shiftb.dev/blog/69KAPGEfqclW
参考になれば幸いです笑