非同期処理 async/await

非同期処理 async/await

投稿日: 2025年02月22日

学習振り返り
Tips
要約
  • 非同期処理は、処理を待たずに進めるプログラミングの仕組みで、API通信やデータベースとのやり取りなどでよく使用される。
  • APIから取得したデータはJSON形式に変換し、フロント側で使いやすいデータに整形される。
  • 未ログインユーザーはリクエストを送れず、トークンの状態でデータ取得が制御されている。

はじめに

今回復習として、非同期処理について軽く書こうと思っています!
間違っていたらコメントいただけると嬉しいです😎

非同期処理

非同期処理というのは、処理が終わるのを待たずに、次の処理を進めることができる。
同期処理は、順番通りに実行され、前の処理が終わるまで次の処理が待機する。

よくある非同期処理の使い方の例

  • API通信(fetch, axios など)

  • データベースとのやり取り

  • ファイルの読み込み(画像、動画)

  • タイマー(setTimeout, setInterval

  • ユーザーの操作待ち(クリック、スクロールなど)

  • WebSocket(リアルタイム通信)

  • 画像のアップロード

  • 非同期的な計算(Web Workers)

ShiftBでよく使われるのは、API通信画像のアップロードユーザーの操作待ち(クリック、スクロールなど)?とかですかね。

非同期処理と同期処理の特徴

実行の流れ

  • 同期処理 は、コードが 上から順番に 実行される。
    前の処理が終わらないと、次の処理に進まない

  • 非同期処理 は、処理が並行して実行されることがある。
    処理を待たずに、次の処理に進むことができる

処理の待ち時間

  • 同期処理 は、 前の処理が完全に終わるまで、次の処理は実行されない
    例えば、計算処理の結果が出るまで待つ必要がある

  • 非同期処理 は、 処理が終わるのを待たずに、他の処理を進めることができる
    必要なら await を使って、一時的に処理を待つことも可能

API通信・データベースアクセス

  • 同期処理 では、APIのレスポンスが返るまで プログラム全体がストップ する。
    この間、ユーザーが画面操作できなくなる可能性もある

  • 非同期処理 では、 APIのレスポンスを待つ間に、他の処理を進めることができる
    UIの動作を止めずに、スムーズな処理ができる

非同期処理の使用例(API通信)

  1. 以下のコードでは、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 に変換

  1. 取得したデータを 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

参考になれば幸いです笑

シェア!

Threads
Loading...
記事一覧に戻る
Threads
0