简体   繁体   English

使用带有 nodejs 的服务器发送事件并做出反应的问题

[英]problem using server sent events with nodejs and react

I need to implement server-sent-events to my node js and react application, I did some research about this and I had followed some tutorials online especially this site because of its simplicity.我需要在我的node js和 react 应用程序中实现server-sent-events ,我对此做了一些研究,并且我已经在网上学习了一些教程,尤其是这个站点,因为它很简单。

my goal is that there is 1 route called /api/alert我的目标是有 1 条名为 /api/alert 的路由

if we make an HTTP POST request to this route with a JSON object like如果我们使用像这样的 JSON 对象向该路由发出 HTTP POST 请求

{
  "longtitude": 100, 
  "latitude": 35, 
  "userId": "5dc28160e8a69c203002383b"
}

then the server will store it in the MongoDB and also send it to the client in realtime (using server-sent events of course)然后服务器将其存储在 MongoDB 中并实时发送给客户端(当然使用服务器发送的事件)

if we make the HTTP GET request to this route then it will show all the current objects in MongoDB and it will get the new object every time a new object is POST.如果我们向该路由发出HTTP GET请求,那么它将显示MongoDB 中的所有当前对象,并且每次 POST 新对象时它都会获取新对象。

it worked like just like how I want it.它就像我想要的那样工作。 But a problem came up.但是出现了一个问题。 it displays the objects in DB and the new one in real-time just fine until exactly 2 minutes later, somehow the connection is lost or something happens that makes the browser call to the GET /api/alert again then all the same data which is already displayed got displayed again.它实时显示 DB 中的对象和新的对象,直到正好 2 分钟后,不知何故连接丢失或发生某些事情使浏览器再次调用 GET /api/alert 然后所有相同的数据已经显示再次显示。 the duplication happen every 2 minutes as long as i do nothing to it.只要我不做任何事情,重复每 2 分钟就会发生一次。

i did a lot of research on the我做了很多研究

Failed to load resource: net::ERR_INCOMPLETE_CHUNKED_ENCODING无法加载资源:net::ERR_INCOMPLETE_CHUNKED_ENCODING

and try different ways to work around but it doesn't seem to help at all.并尝试不同的方法来解决,但它似乎根本没有帮助。

is this a nodejs or react problem.这是 nodejs 还是反应问题。 Any idea on what i did wrong or something to do with this problem.关于我做错了什么或与这个问题有关的任何想法。 All help is appreciated.感谢所有帮助。

these are my code, it is based on most of the what find on this https://alligator.io/nodejs/server-sent-events-build-realtime-app/ :这些是我的代码,它基于在这个https://alligator.io/nodejs/server-sent-events-build-realtime-app/上找到的大部分内容:

Nodejs code:节点代码:

const { Fire } = require("../models/fire");

let clients = [];

// Iterate clients list and use write res object method to send new nest
function sendEventsToAll(newFire) {
  clients.forEach(c => {
    c.res.write(`data: ${JSON.stringify(newFire)}\n\n`);
  });
}

module.exports.addAlert = async (req, res, next) => {
  const fire = new Fire(req.body);
  res.send(await fire.save());

  return sendEventsToAll(fire);
};

module.exports.handleAlert = async (req, res, next) => {
  const headers = {
    "Content-Type": "text/event-stream",
    Connection: "keep-alive",
    "Cache-Control": "no-cache"
  };
  res.writeHead(200, headers);
  res.flushHeaders();

  const data = await Fire.find();
  res.write(`data: ${JSON.stringify(data)}\n\n`);

  // Generate an id based on timestamp and save res
  // object of client connection on clients list
  // Later we'll iterate it and send updates to each client
  const clientId = Date.now();
  const newClient = {
    id: clientId,
    res
  };
  clients.push(newClient);
  console.log(`${clientId} Connection opened`);

  // When client closes connection we update the clients list
  // avoiding the disconnected one
  req.on("close", () => {
    console.log(`${clientId} Connection closed`);
    clients = clients.filter(c => c.id !== clientId);
    res.end();
  });
};

React code:反应代码:

import React, { useState, useEffect } from "react";
import "./App.css";

function App() {
  const [nests, setNests] = useState([]);
  const [listening, setListening] = useState(false);

  useEffect(() => {
    if (!listening) {
      const events = new EventSource("http://localhost:3900/api/alert");
      events.onmessage = event => {
        const parsedData = JSON.parse(event.data);

        setNests(nests => nests.concat(parsedData));
      };

      setListening(true);
    }
  }, [listening, nests]);

  return (
    <table className="stats-table">
      <thead>
        <tr>
          <th>_id</th>
          <th>longtitude</th>
          <th>latitude</th>
          <th>userId</th>
        </tr>
      </thead>
      <tbody>
        {nests.map((nest, i) => (
          <tr key={i}>
            <td>{nest._id}</td>
            <td>{nest.longtitude}</td>
            <td>{nest.latitude}</td>
            <td>{nest.userId}</td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}
export default App;

Image of the problem I encountered我遇到的问题的图片

我遇到的问题的图片

Nodejs has 2-minute default timeout that's why your connection has closed after two minutes. Nodejs 有 2 分钟的默认超时,这就是您的连接在两分钟后关闭的原因。 If you want it to open for longer period then you need to increase the default timeout.如果您希望它打开更长的时间,则需要增加默认超时时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM