網站搜尋

node.js - React EventSource 有時無法從 NodeJs 後端獲取資料


我正在使用一個 React 組件從伺服器獲取即時資料。我使用 EventSource 並監聽我的伺服器端點。我接收到資料的頻率是……80%。從後端我從 MongoDB 收到的資料是 100%,但當我將它們發送到前端時,我並不總是能收到它們。

我在瀏覽器的控制台或網路標籤中沒有錯誤。

伺服器:

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);
};

當 React 客戶端:

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
  }, []);

我能毫無問題地獲取即時數據,唯一的問題是並非所有數據都傳送到客戶端。例如,6/10 條消息能正確接收,有時是 1/15,這非常隨機。控制台沒有錯誤,連線也始終保持活躍。我在網上找不到任何解決方案。

編輯:看起來我只需要那一行 res.write("data: myData\n\n") 來使用 onmessage() 監聽器。否則,如果在資料之前有其他東西,監聽器似乎不會總是收到訊息。現在,如果我刷新頁面,會遇到同樣的問題,但如果我同時重置伺服器和頁面,它仍然能正常運作並收到 100% 的訊息。