• 作者:老汪软件技巧
  • 发表时间:2024-09-04 00:04
  • 浏览量:

本文介绍了如何在 Next.js 中设置和实现服务器发送事件 (SSE) 以实现实时数据流。

1. 服务器端实现

首先,我们需要在服务器端创建一个 SSE 端点,以便客户端可以通过这个端点接收实时数据:

_Next.js 中实现服务器发送事件 (SSE)_Next.js 中实现服务器发送事件 (SSE)

// app/api/sse/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
    const encoder = new TextEncoder();
    const readableStream = new ReadableStream({
        start(controller) {
            const intervalId = setInterval(() => {
                // 检查流是否已关闭
                if (controller.desiredSize === null) {
                    // 流已关闭,停止发送数据
                    clearInterval(intervalId);
                    return;
                }
                const data = JSON.stringify({ time: new Date().toISOString() });
                try {
                    controller.enqueue(encoder.encode(`data: ${data}\n\n`)); // 推送数据
                } catch (error) {
                    console.error('Error enqueueing data:', error);
                    clearInterval(intervalId);
                }
            }, 1000);
            // 设置连接保持时间(可选)
            const keepAlive = setTimeout(() => {
                clearInterval(intervalId);
                controller.close();
            }, 30000); // 30 秒后自动关闭连接
            // 使用 request.signal 监听客户端断开连接
            request.signal.addEventListener('abort', () => {
                clearInterval(intervalId);
                clearTimeout(keepAlive);
                controller.close();
            });
        },
    });
    return new NextResponse(readableStream, {
        headers: {
            'Content-Type': 'text/event-stream',
            'Cache-Control': 'no-cache',
            'Connection': 'keep-alive',
        },
    });
}

2. 客户端实现

客户端需要使用 EventSource API 来接收从服务器推送的数据:

// app/page.tsx
'use client';
import * as React from 'react';
export default function Home() {
  const [messages, setMessages] = React.useState<string[]>([]);
  React.useEffect(() => {
    const eventSource = new EventSource('/api/sse');
    eventSource.onmessage = function (event) {
      console.log("data",event)
      const newMessage = JSON.parse(event.data);
      setMessages((prevMessages) => [...prevMessages, newMessage.time]);
    };
    // 清除 EventSource 连接
    return () => {
      eventSource.close();
    };
  }, []);
  return (
    <div>
      <h1>实时推送的消息:h1>
      <ul>
        {messages.map((message, index) => (
          <li key={index}>{message}li>
        ))}
      ul>
    div>
  );
}