Мне нужно реализовать server-sent-events
для моего node js
и реагировать приложения, я провел некоторое исследование по этому поводу, и я следовал некоторым учебникам в Интернете, особенно на этом сайте из-за его простоты.
моя цель состоит в том, чтобы был 1 маршрут под названием / api / alert
, если мы сделаем HTTP-запрос POST к этому маршруту с объектом JSON, таким как
{
"longtitude": 100,
"latitude": 35,
"userId": "5dc28160e8a69c203002383b"
}
, то сервер сохранит его в MongoDB, а также отправит его клиенту в режиме реального времени (конечно, используя отправленные сервером события)
, если мы сделаем запрос HTTP GET на этот маршрут, то он покажет все текущие объекты в MongoDB , и он будет получать новый объект каждый раз, когда новый объект POST.
он работал так же, как я этого хочу. Но возникла проблема. он отображает объекты в БД и новый в режиме реального времени очень хорошо, пока ровно через 2 минуты, каким-то образом соединение теряется или происходит что-то, что заставляет браузер снова вызвать GET / api / alert, а затем все те же данные, которые уже отображается снова отображается. Дублирование происходит каждые 2 минуты, пока я ничего не делаю с ним.
Я много исследовал
Не удалось загрузить ресурс: net :: ERR_INCOMPLETE_CHUNKED_ENCODING
и попробуйте разные способы обхода, но это, похоже, совсем не помогает.
это nodejs или проблема реагирования. Любая идея о том, что я сделал не так или что-то делать с этой проблемой. Любая помощь приветствуется.
это мой код, он основан на большинстве того, что можно найти по этому https://alligator.io/nodejs/server-sent-events-build-realtime-app/:
Nodejs код:
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();
});
};
Код реакции:
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;
Изображение проблемы, с которой я столкнулся