Я пытался запустить и запустить базовые события, отправленные сервером, используя следующий код (nodejs + Express для бэкэнда и React на внешнем интерфейсе), однако onmessage
не срабатывает, когда я пытаюсь обновить count
через терминал.
Вот поток:
- Поднимите сервер и запустите его.
- Откройте браузер и нажмите
localhost:9000
. - В пользовательском интерфейсе я вижу, что счетчик уведомлений равен
0
. - Попытка обновить счетчик уведомлений с помощью вызова
POST
в терминале через cURL, как показано ниже:
curl -X POST -H Content-Type: application/json -d '{count: 10}' -s http://localhost:9000/notification
- В оболочке терминала, где работает сервер, я вижу, что обратный вызов
/events
запускается, однакоcount
все еще0
.
Вот код, который я пробовал. Получение ошибки, как указано в теме (видно в консоли браузера), и пользовательский интерфейс не обновляется с обновленным счетчиком уведомлений. Пожалуйста, дайте мне знать, что я делаю неправильно:
Код сервера (NodeJS+Express):
const sseHandler = (req: express.Request, res: express.Response) => {
console.log("server sent event handler triggered");
//Mandatory headers and http status to keep connection open
const headers = {
'Content-Type': 'text/event-stream',
'Connection': 'keep-alive',
'Cache-Control': 'no-cache'
};
res.writeHead(200, headers);
//After client opens connection send all notifications as string
const data = `count:${notificationCount}\n\n`;
console.log(data);
res.write(data);
// 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
// In Real world scenario, client list should be saved to the DB
const clientId = Date.now();
const newClient = {
id: clientId,
res,
};
clients.push(newClient);
// 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);
});
};
// Iterate clients list and use write res object method to send latest notification count
const sendEventsToAll = (count:number) => {
console.log("send event to all");
clients.forEach(c => c.res.write(`count:${count}\n\n`));
};
// Middleware for POST /notification endpoint
const updateNotification = async (
req: express.Request,
res: express.Response,
) => {
let currentCount= req.body.count;
console.log("post count is: ", currentCount);
// Send recently updated notification count as POST result
res.json({count: currentCount});
// Invoke iterate and send function
return sendEventsToAll(currentCount);
}
Реагировать на код
const Nav = () => {
const router = useRouter();
const [ notificationCount, setNotificationCount ] = useState(0);
useEffect(() => {
console.log("rendered on client");
const events = new EventSource('http://localhost:9000/events');
events.onmessage = (event) => {
console.log("Entering on message callback");
console.log(event);
// console.log(event.data);
// const parsedData = JSON.parse(event.data);
// setNotificationCount(() => parsedData.count);
};
}, [notificationCount]);
// record rendering counter
metrics.recordCounter({
name: "NavBar",
eventName: "render",
value: 1,
});
return (
<nav>
<ul>
<li className={router.pathname === "/" ? "active" : ""}>
<Link href="/">
<a>Home</a>
</Link>
</li>
<li className={router.pathname === "/dangerously_set" ? "active" : ""}>
<Link href="/xss-testing">
<a>XSS Testing</a>
</Link>
</li>
{links.map(({ key, href, label }) => (
<li key={key}>
<a href={href}>{label}</a>
</li>
))}
<a href="#" className="notification">
<span>Notification</span>
<span className="badge">{notificationCount}</span>
</a>
</ul>
);
}