I'm using a React component to get real-time data from server. I'm using EventSource and listening on my server endpoint. I receive data... 80% of the time. From the backend I receive 100% data from MongoDB, but when I send them to the frontend, I don't always get them.
I have no error in console or network tab on the browser.
Server:
export const realTimeLogs = async (req: Request, res: Response) => {
res.writeHead(200, {
Connection: 'keep-alive',
'Keep-Alive': 'timeout=3600, max=10',
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Transfer-Encoding': 'chunked',
'Access-Control-Allow-Origin': 'http://localhost:3000',
'Access-Control-Allow-Credentials': 'true',
'X-Accel-Buffering': 'no',
});
res.write(''); //Without this, the EventSource.open event would not get triggered.
writeStream(res);
}
const writeStream = async (res: Response) => {
const msg: ReceiveMessageCommandOutput = await createAndReceiveMessage(
'mySQSQueue'
); //Get data from SQS
if (msg.Messages) {
const msgBody: string | undefined = msg.Messages[0].Body;
console.log(`${msgBody}`); //The server gets 100% of the messagges, I see it here.
const receiptHandle: string | undefined = msg.Messages[0].ReceiptHandle;
setTimeout(() => {
res.write('retry: 10000\n', 'utf-8');
res.write(`id: ${JSON.parse(msgBody!).payload._id}\n`, 'utf-8');
res.write('event: message\n');
res.write(`data: ${msgBody}\n\n`, 'utf-8'); //THIS IS HOW REACT CLIENT SHOULD GET DATA
}, 0);
if (receiptHandle)
await createAndDeleteMessage('mySQSQueue', receiptHandle);
}
let timeout = setTimeout(() => {
clearTimeout(timeout);
return writeStream(res); //Re-call this function as infinite loop.
}, 5000);
};
While the React Client:
useEffect(() => {
console.log('RE-RENDER');
const source = new EventSource(
`${BASE_URL}/${ROOT_ENDPOINTS.MANAGER}/${MANAGER_ENDPOINTS.GETREALTIMELOGS}`,
{
withCredentials: true,
}
);
source.onopen = (event: Event) => {
console.log('OnOpen: ', event);
};
source.onerror = (event: Event) => {
console.error('Errore: ', event);
};
source.onmessage = (event: MessageEvent) => {
let payload: MSGManager;
try {
payload = JSON.parse(event.data);
eventSourceHandler(payload);
} catch (e) {
console.error('errore: ', e);
}
};
setEventSource(source);
return () => {
console.log('CLEANUP');
eventSource?.close();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
I get real time data with no problem, the only problem is that not all goes to the client. For example, 6/10 messagges are correctly received, sometimes 1/15, this is so random. There is no errors in console and the connection always stays active. I can't find any solution on the net.
EDIT: It seems that I need only the line res.write("data: myData\n\n") to use the onmessage() listener.
Otherwise it seems that the listener not always gets the message if something is before data. Now, if I refresh the page, I get the same problem, but if I also reset the server, and the page, still working and getting 100% of messagges.