React EventSource sometimes doesn't get data from NodeJs Backend

Viewed 137

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.

0 Answers
Related