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
202 stars 30 forks source link

Event Listener didn't trigger 'close' event #53

Closed anhphamtien closed 4 months ago

anhphamtien commented 4 months ago

package.jgon

"expo": "~50.0.14",
"react-native-sse": "^1.2.1",

use

import EventSource from 'react-native-sse';

const es = useRef<EventSource | null>(null);

useEffect(() => {
    return () => {
        if (es.current) {
            es.current.removeAllEventListeners();
            es.current.close();
        }
    };
}, []);

const onSendMessage = async (message: string) => {
    es.current = new EventSource(`api/messages`, {
        method: 'POST',
        headers: {
            Accept: 'text/event-stream',
            Authorization: `Bearer ${authJWTToken}`,
        },
        body: JSON.stringify({
            text: message,
            streaming: true,
            token_size: 50,
        }),
        pollingInterval: 0,
        debug: true,
    });

    es.current.addEventListener('open', (event) => {
        console.log('Open SSE connection.'); // Logged βœ…
    });

    es.current.addEventListener('message', (event) => {
        console.log('πŸš€ ~ es.current.addEventListener ~ event:', event.data); // Logged βœ…
    });

    es.current.addEventListener('close', (event) => {
        console.log('Close SSE connection.'); // Didn't Logged ❌
    });

    es.current.addEventListener('error', (event) => {
        if (event.type === 'error') {
            console.error('Connection error:', event.message);
        } else if (event.type === 'exception') {
            console.error('Error:', event.message, event.error);
        }
    });
};

Log

image

anhphamtien commented 4 months ago

SOLVED In my case, I want trigger event 'close' when server is down without _pollAgain so I add the else condition

_pollAgain(time, allowZero) {
    if (time > 0 || allowZero) {
        this._logDebug(`[EventSource] Will open new connection in ${time} ms.`);
        this._pollTimer = setTimeout(() => {
            this.open();
        }, time);
    }
    // custom code
    else {
        this.dispatch('close', { type: 'close' });
    }
}
EmilJunker commented 4 months ago

The only time react-native-sse will emit a close event is when the client closes the connection, i.e. by calling es.close().

When the server closes the connection, the client just automatically reopens it (unless you set pollingInterval to 0). No close event gets emitted in this case.

In other words, what you are seeing is the expected behavior and in line with the SSE protocol. SSE connections are not really meant to be closed by the server. They normally just stay open until the client closes them.