Skip to content

Conversation

feggaa
Copy link

@feggaa feggaa commented Jul 19, 2025

No description provided.

@EmilJunker
Copy link
Contributor

Why would you need an autoConnect option? If you want to disable the automatic reconnect, you can just set the pollingInterval to 0.

And instead of adding a new isConnected function, it would be both easier and more useful to expose the status property of the EventSource class.

@feggaa
Copy link
Author

feggaa commented Sep 2, 2025

Thank you for your question

I need it for create instance of eventSource without connect

then I control connection by call eventSource.open() or eventSource.close()

this small example how I use it

type tEvent = {
    type: 'data' | 'error' | 'close' | 'remove';
    data: string | null;
    eventId : string;
}

const eventSource = new EventSource(global.serverUrl + 'serverEvents',{autoConnect: false});

function subscribeToEvent(api : string,args: string,eventId : string) {
    return fetch(global.serverUrl + 'serverEvents', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({api,args,eventId}),
    })
}

const listeners = new Map<string, (data :any)=> any>();

export function startListening<T>(api : string,callback : (data : T)=>void,args : any){
    if(!eventSource.isConnected){
        eventSource.open();
    }
    const eventHash = crc32.str(api +':'+ JSON.stringify(args)).toString()
    const randomId = Math.random().toString(36).substring(2, 15);
    const eventId = eventHash + ':' + randomId;
    subscribeToEvent(api,args,eventId)
    listeners.set(eventId,callback);

    return () => {
        listeners.delete(eventId);
        if (listeners.size === 0) {
            eventSource.close();
        }
    }
}

eventSource.addEventListener('message', (event) => {
    const data : tEvent | null = event.data ? JSON.parse(event.data) : null;
    if(!data) return
    const {type, data: eventData, eventId} = data;

    if (type === 'data') {
        const callback = listeners.get(eventId);
        const cache = storage.getString(eventId);
        if (cache) {
            callback?.(JSON.parse(cache));
        }
        callback?.(eventData);
    } else if (type === 'error') {
        console.error('Error event:', eventData);
    } else if (type === 'close') {
        eventSource.close();
        console.log('Connection closed');
    } else if (type === 'remove') {
        listeners.delete(eventId);
        console.log('Listener removed for eventId:', eventId);
    }
})
eventSource.addEventListener('error', (event) => {
    console.error('Error event:', event);
});

AppState.addEventListener('change', (state) => {
    if (state === 'active') {
        eventSource.open();
    } else {
        eventSource.close();
    }
})

export function useEventSource({api, args} : {api : string, args : any}) {
    const [_args, setArgs] = useState(args);
    const [data, setData] = useState<any>(null);
    const [eventId, setEventId] = useState<string | null>(null);
    
    useEffect(() => {
        const eventHash = crc32.str(api +':'+ JSON.stringify(args)).toString()
        const randomId = Math.random().toString(36).substring(2, 15);
        const eventId = eventHash + ':' + randomId;
        subscribeToEvent(api,args,eventId)
        listeners.set(eventId,setData);
        setEventId(eventId);
        return () => {
            listeners.delete(eventId);
            if (listeners.size === 0) {
                eventSource.close();
            }
        }
    },[_args])

    return {
        data,
        eventId,
        setArgs,
        remove : () => {
            if (!eventId) return;
            listeners.delete(eventId);
            if (listeners.size === 0) {
                eventSource.close();
            }
        },
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants