最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - EventSource gets all chunks at once when streaming via Nextjs API Routes - Stack Overflow

programmeradmin2浏览0评论

Problem

I am trying to stream data to my React Frontend via EventSources, which kind of works. The problem is that I receive all chunks of data at once instead of time after time. Which kind of defeats the purpose of the method as it is basically now a GET request.

Code

I am using Next.js api routes and this is my code on this route:

res.writeHead(200, {
  "Content-Type": "text/event-stream",
  "Cache-Control": "no-cache",
  Connection: "keep-alive",
});

answerStream.data
  .on("data", (chunk: string) => res.write(chunk))
  .on("error", (error: Error) => {
    console.error(error);
    res.end();
  })
  .on("end", () => res.end());

This is the code in the Frontend:

  const eventSource = new EventSource(url);
  eventSource.addEventListener("message", e => {
    try {
      if (e.data == "[DONE]") eventSource.close();
      else {
        const messageObject = JSON.parse(e.data);
        setArticle(state => (state += messageObject?.choices[0]?.text));
      }
    } catch (error) {
      console.log(error);
    }
  });

  eventSource.addEventListener("close", e => {
    console.log("Connection closed with the server");
    setSubmitting(false);
  });

  eventSource.addEventListener("error", e => {
    setError(e?.message || "Leider ist ein Fehler aufgetreten");
    setSubmitting(false);
    eventSource.close();
  });

Info

Is there anything in my implementation wrong? Or does Next.js have a strange handling of EventSource?

Problem

I am trying to stream data to my React Frontend via EventSources, which kind of works. The problem is that I receive all chunks of data at once instead of time after time. Which kind of defeats the purpose of the method as it is basically now a GET request.

Code

I am using Next.js api routes and this is my code on this route:

res.writeHead(200, {
  "Content-Type": "text/event-stream",
  "Cache-Control": "no-cache",
  Connection: "keep-alive",
});

answerStream.data
  .on("data", (chunk: string) => res.write(chunk))
  .on("error", (error: Error) => {
    console.error(error);
    res.end();
  })
  .on("end", () => res.end());

This is the code in the Frontend:

  const eventSource = new EventSource(url);
  eventSource.addEventListener("message", e => {
    try {
      if (e.data == "[DONE]") eventSource.close();
      else {
        const messageObject = JSON.parse(e.data);
        setArticle(state => (state += messageObject?.choices[0]?.text));
      }
    } catch (error) {
      console.log(error);
    }
  });

  eventSource.addEventListener("close", e => {
    console.log("Connection closed with the server");
    setSubmitting(false);
  });

  eventSource.addEventListener("error", e => {
    setError(e?.message || "Leider ist ein Fehler aufgetreten");
    setSubmitting(false);
    eventSource.close();
  });

Info

Is there anything in my implementation wrong? Or does Next.js have a strange handling of EventSource?

Share Improve this question asked Jan 27, 2023 at 10:34 Gh05dGh05d 9,02211 gold badges41 silver badges82 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

Solution

Ok, I have found the solution in this Github discussion:

It seems the issue is that the middleware adds a gzip encoding which the browser has negotiated using the header

In order to fix this, it is needed to overwrite that behavior by adding 'Content-Encoding': 'none' to the headers on the server:

res.writeHead(200, {
    Connection: 'keep-alive',
    'Content-Encoding': 'none',
    'Cache-Control': 'no-cache',
    'Content-Type': 'text/event-stream',
  });

Alternatively, one could use a custom server.js.

yessssss this is what i was looking for, had something similar, spent about 2 days of frustration trying to figure out. heres what i ended up doing/having in addition there was a chunk header that i was experimenting with:

  res.setHeader("Content-Type", "text/event-stream");
  res.setHeader("Cache-Control", "no-cache");
  res.setHeader("Connection", "keep-alive");
  res.setHeader("Transfer-Encoding", "chunked");
  res.setHeader("Content-Encoding", "none");
发布评论

评论列表(0)

  1. 暂无评论