LoginSignup
2
0

Next.js APP (ver14) SSEのサンプルコード

Posted at

NEXTJS SSEのサンプルコードです。

NextResponse でのサンプルコードがあまり見つからないので

  • src/app/api/xxxの場合

サーバー側

import { NextRequest, NextResponse } from "next/server";

/*
sse通信のサンプルコード
 */

export async function GET(req:NextRequest) {
    const stream = new TransformStream()
    // 以下のwriterにメッセージを入れるとストリーミングメッセージとなる writer.write(message)
    const writer = stream.writable.getWriter()
    const encoder = new TextEncoder()

    // 1秒後にファイルチェックの結果を流し込む 改行2個がデータエンドなので消さないこと。本文中の改行連続はエンコーダーで処理されており保存される
    setTimeout(() => {
        const message = encoder.encode(`data: ${JSON.stringify('File has been checked')}\n\n`);
        writer.write(message);
        console.log(message);
    }, 1000);

    // 2秒後にファイル解析の結果を流し込む
    setTimeout(() => {
        const message = encoder.encode(`data: ${JSON.stringify('File has been parsed')}\n\n`);
        writer.write(message);
        console.log(message);
    }, 2000);

    // 3秒後に接続を閉じる
    setTimeout(() => {
        writer.close();
        console.log("finish")
    }, 3000);

    return new NextResponse(stream.readable, {
        headers: {
            'Content-Type': 'text/event-stream',
            Connection: 'keep-alive',
            'Cache-Control': 'no-cache, no-transform',
        },
    });
}

クライアント側

'use client'
import { useState, useEffect } from 'react';
/*
SSE通信のモデルコード
 */



const UploadComponent = () => {
    const [status, setStatus] = useState<string>('');

    useEffect(() => {
        const handleEventSourceMessage = (event:any) => {
            setStatus(JSON.parse(event.data));
        };

        const handleEventSourceError = () => {
            eventSource.close(); // 接続が閉じられたら EventSource を明示的に閉じる
        };

        const eventSource = new EventSource('/api/sample/sse');

        eventSource.addEventListener('message', handleEventSourceMessage);
        eventSource.onerror = handleEventSourceError; // エラーハンドラを追加

        return () => {
            eventSource.removeEventListener('message', handleEventSourceMessage);
            eventSource.close();
        };
    }, []);
    const handleUpload = () => {
        // TODO: 実際のアップロードロジック
        // axios などを利用してファイルをサーバに POST
        // 成功したら以下を実行
        setStatus('File has been uploaded');
    };

    return (
        <div>
            <button onClick={handleUpload}>Upload File</button>
            <p>Status: {status}</p>
        </div>
    );
};

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0