fetch-event-source icon indicating copy to clipboard operation
fetch-event-source copied to clipboard

fetchEventSource() repeats request indefinitely

Open Blabter opened this issue 1 year ago • 10 comments

I have SSE-endpoint http://localhost/sse-endpoint that returns next data:

data:{text: "He"}
id:0

data:{text: "ll"}
id:2

data:{text: "o,"}
id:4

data:{text: " u"}
id:6

data:{text: "se"}
id:8

data:{text: "r!"}
id:10

I use this client code to fetch data:

import { fetchEventSource } from "@microsoft/fetch-event-source";

console.log('Start');
fetchEventSource("http://localhost/sse-endpoint"), {
  method: "POST",
  onmessage(ev) {
    console.log('Received data');
    console.log(ev.data);
  }
});

Expected output:

Start
Received data
{text: "He"}
Received data
{text: "ll"}
Received data
{text: "o,"}
Received data
{text: " u"}
Received data
{text: "se"}
Received data
[{text: "r!"}

Actual output:

Start
Received data
{text: "He"}
Received data
{text: "ll"}
Received data
{text: "o,"}
Received data
{text: " u"}
Received data
{text: "se"}
Received data
[{text: "r!"}
Received data
{text: "He"}
Received data
{text: "ll"}
Received data
{text: "o,"}
Received data
{text: " u"}
Received data
{text: "se"}
Received data
[{text: "r!"}
// Output continues infinitely

In devtools tab "Network" I can see that requests to /sse-endpoint continues indefinitely

Blabter avatar Apr 13 '24 00:04 Blabter

make sure your server code is responding with:

  res.setHeader('Cache-Control', 'no-cache, no-transform');
  res.setHeader('Connection', 'keep-alive');
  res.setHeader('Content-Type', 'text/event-stream');
  res.flushHeaders();

sahilhaslani avatar Apr 28 '24 01:04 sahilhaslani

make sure your server code is responding with:

  res.setHeader('Cache-Control', 'no-cache, no-transform');
  res.setHeader('Connection', 'keep-alive');
  res.setHeader('Content-Type', 'text/event-stream');
  res.flushHeaders();

It's external server and I can't control it, but it has following HTTP response headers:

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: keep-alive
Content-Type: text/event-stream

Blabter avatar May 23 '24 20:05 Blabter

This will only happen when server keeps sending you events. On message only fires when server sends events. To mitigate this (since you don't have control over the server): call abort using an AbortController once you get a set of messages you need and reconnect when you need them again.

sameert89 avatar Jun 14 '24 13:06 sameert89

Set the "openWhenHidden" true and can be solved. fetchEventSource(API, { openWhenHidden: true })

ningxiner0201 avatar Jun 21 '24 03:06 ningxiner0201

vConsole may cause this issue, remove it.

congjinruo avatar Oct 21 '24 09:10 congjinruo

Set the "openWhenHidden" true and can be solved. fetchEventSource(API, { openWhenHidden: true })

This Solved my issue, thanks alot. It would be helpful if you could provide some explanation about this.

Alwaz avatar Apr 18 '25 12:04 Alwaz

Set the "openWhenHidden" true and can be solved. fetchEventSource(API, { openWhenHidden: true })

This Solved my issue, thanks alot. It would be helpful if you could provide some explanation about this.

@Alwaz * If openWhenHidden is true, it will keep the request open even if the document is hidden. * By default, fetchEventSource will close the request and reopen it * automatically when the document becomes visible again. https://github.com/Azure/fetch-event-source/blob/main/src/fetch.ts#L45C5-L48C62

albedj avatar Jul 03 '25 02:07 albedj

Set the "openWhenHidden" true and can be solved. fetchEventSource(API, { openWhenHidden: true })

This Solved my issue, thanks alot. It would be helpful if you could provide some explanation about this.

@Alwaz * If openWhenHidden is true, it will keep the request open even if the document is hidden. * By default, fetchEventSource will close the request and reopen it * automatically when the document becomes visible again. https://github.com/Azure/fetch-event-source/blob/main/src/fetch.ts#L45C5-L48C62

This was causing my issue, when I alt tab out and tab back in, it sends another request

AChangXD avatar Jul 31 '25 12:07 AChangXD

Ran into this today and found another possible cause. Looks like fetchEventSource does not provide a default error handler. I had a bug in my onmessage, but it was getting swallowed up with no logs. Just shove console.error into the options and you'll start seeing the real issue in the console.

await fetchEventSource("http://localhost:3000/stream", {
  onmessage,
  onerror: console.error,
})

iandoesallthethings avatar Sep 17 '25 20:09 iandoesallthethings

In my case, I set "openWhenHidden" to False, but the request never close. It will always run into "onerror" but not "onclose". So I throw an error In "onerror" then it stop. btw, I run it in a Android webview page.

zero5396517 avatar Nov 20 '25 07:11 zero5396517