Azure / Azure/fetch-event-source

Can't close `fetchEventSource` with `AbortController` in React

Open
#84 6 comments 6 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
2.9k
Forks
196
PR merge metrics
No merged PRs in 30d

Description

Hello. I'm aware this topic has been raised many times here already, and I have read all of those issues with no success. Indeed, in most cases those issues have comments from people saying the proposed solution didn't work for them either. I am running my app in `React.StrictMode`, which causes each component to mount/unmount/remount to help identify unexpected side-effects and so on. In my case this is causing two `fetchEventSource` requests to be fired, which is expected. What's unexpected, is that using an `AbortController` does not close the first connection on unmount. This is my hook:

```javascript
const useStreamTradingNotifications = () => {
const [ abortController, setAbortController ] = useState(new AbortController());
useEffect(() => {
console.log("useEffect called");
const stream = async () => {
await fetchEventSource("http://127.0.0.1:8000/v1/notifications", {
signal: abortController.signal,
onmessage(msg) {
if (abortController.signal.aborted){
console.log("still getting messages from aborted signal")
}
console.log(`event: ${msg.event}`)
if (msg.event == "update") {
console.log(JSON.parse(msg.data))
}
},
});
};
stream();
return () => {
console.log("abort called")

abortController.abort();
setAbortController(new AbortController());
}
}, []);
};
```

When I run my app, I see the following logs:
![image](https://github.com/Azure/fetch-event-source/assets/4462726/1e90a9a0-59de-4db4-a1ee-c5c5787b0248)

As you can see:
1. `useEffect` is called twice, as the component is mounted/unmounted/remounted [expected]
2. `abortController.abort` is called when the first component unmounts [expected]
3. Subsequently I receive two of each message (the logs above are truncated, and just includes the first duplicate). For one of the two streams, I can confirm that the messages are being received on an already-aborted connection (`still getting messages from aborted signal`).

Furthermore, in my backend logs, when I close a browser window with an active connection I see a log like:
```
[2024-07-09T11:13:37.409247Z][sse_starlette.sse][DEBUG] Got event: http.disconnect. Stop streaming.
```
But I never see this message as the result of `AbortController.abort` being called. I have tried assigning a new instance of `AbortController` after abort (as suggested [here](https://github.com/Azure/fetch-event-source/issues/24#issuecomment-1691426586)), which had no affect. I have tried doing a similar thing with `setState` (as mentioned [here](https://github.com/Azure/fetch-event-source/issues/24#issuecomment-1762053484)) which made the problem much worse (kept creating connections until the browser crashed). I tried to use `useRef` to manage the controller (suggested [here](https://github.com/Azure/fetch-event-source/issues/24#issuecomment-1796842392), which also doesn't work.

The fact that I can see `abort` being called, but never see a `http.disconnect` on the backend, convinces me this must be a bug. But if anybody has a suspicion that I've screwed something up I'd really appreciate their suggestion.

Many thanks

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.