binaryminds / react-native-sse

Event Source implementation for React Native. Server-Sent Events (SSE) for iOS and Android 🚀
https://www.npmjs.com/package/react-native-sse
MIT License
174 stars 27 forks source link

The close() method does not reliably close the SSE connection #24

Closed EmilJunker closed 8 months ago

EmilJunker commented 11 months ago

Consider the following example:

let sse = new EventSource('https://httpstat.us/404', {
    debug: true,
    pollingInterval: 10000,
});

sse.addEventListener('error', (e) => {
    console.log('There was an error:', e);
    console.log('Closing SSE');
    sse.close();
});

The httpstat.us/404 endpoint always returns a 404 error status. Since I call sse.close() in the error handler, I would expect the SSE connection be closed pretty much immediately after it is created. However, this is not the case. If I run the above code, the SSE keeps trying to reconnect every 10 seconds . Apparently, calling sse.close() does not properly stop the pollingInterval. Here are the logs I get when running the above code (it keeps repeating every 10 seconds):

 DEBUG  [EventSource][onreadystatechange] ReadyState: 2, status: 404
 DEBUG  [EventSource][onreadystatechange] ReadyState: 3, status: 404
 LOG  There was an error: {"message": "404 Not Found", "type": "error", "xhrState": 3, "xhrStatus": 404}
 LOG  Closing SSE
 DEBUG  [EventSource][onreadystatechange] ReadyState: 4, status: 0
 DEBUG  [EventSource][onreadystatechange][ERROR] Response status error. Reconnecting...
 DEBUG  [EventSource][onreadystatechange] ReadyState: 2, status: 404
 DEBUG  [EventSource][onreadystatechange] ReadyState: 3, status: 404
 LOG  There was an error: {"message": "404 Not Found", "type": "error", "xhrState": 3, "xhrStatus": 404}
 LOG  Closing SSE
 DEBUG  [EventSource][onreadystatechange] ReadyState: 4, status: 0
 DEBUG  [EventSource][onreadystatechange][ERROR] Response status error. Reconnecting...
 DEBUG  [EventSource][onreadystatechange] ReadyState: 2, status: 404
 DEBUG  [EventSource][onreadystatechange] ReadyState: 3, status: 404
 LOG  There was an error: {"message": "404 Not Found", "type": "error", "xhrState": 3, "xhrStatus": 404}
 LOG  Closing SSE
 DEBUG  [EventSource][onreadystatechange] ReadyState: 4, status: 0
 DEBUG  [EventSource][onreadystatechange][ERROR] Response status error. Reconnecting...

If I change the error handler to only close the SSE after waiting one second (using setTimeout), then it works:

let sse = new EventSource('https://httpstat.us/404', {
    debug: true,
    pollingInterval: 10000,
});

sse.addEventListener('error', (e) => {
    console.log('There was an error:', e);
    setTimeout(() => {
        console.log('Closing SSE');
        sse.close();
    }, 1000);
});

The 404 error is yielded twice for some reason, but this time closing the connection works:

 DEBUG  [EventSource][onreadystatechange] ReadyState: 2, status: 404
 DEBUG  [EventSource][onreadystatechange] ReadyState: 3, status: 404
 LOG  There was an error: {"message": "404 Not Found", "type": "error", "xhrState": 3, "xhrStatus": 404}
 DEBUG  [EventSource][onreadystatechange] ReadyState: 4, status: 404
 LOG  There was an error: {"message": "404 Not Found", "type": "error", "xhrState": 4, "xhrStatus": 404}
 DEBUG  [EventSource][onreadystatechange][ERROR] Response status error. Reconnecting...
 LOG  Closing SSE
 LOG  Closing SSE

In my opinion, this is a pretty serious bug. The SSE should always stop all its activity when the close() method is called. It certainly shouldn't try to auto-reconnect after this method was called.

Sarvesh-SP commented 10 months ago

@EmilJunker Did you find any workaround? facing the same issue

EmilJunker commented 10 months ago

@Sarvesh-SP The only workaround I found so far is the one I mentioned above. Call the close() method in a setTimeout so it happens a bit later (one second seems to be enough).