Skip to content

Instantly share code, notes, and snippets.

@DashBarkHuss
Created December 17, 2021 21:32
Show Gist options
  • Save DashBarkHuss/294f17803388bd64ab5e472bd5dcd812 to your computer and use it in GitHub Desktop.
Save DashBarkHuss/294f17803388bd64ab5e472bd5dcd812 to your computer and use it in GitHub Desktop.
reconnecting websocket message sent from route node.js react
import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import LiveStorePurchases from "./LiveStorePurchases";
function App(props) {
return (
<div className="App">
<Router>
<Switch>
<Route exact path="/livePurchases/:storeId">
<LiveStorePurchases />
</Route>
</Switch>
</Router>
</div>
);
}
export default App;
const express = require("express");
const NotifierService = require("../server/NotifierService.js");
const notifier = new NotifierService();
const http = require("http");
const routes = require("./routes");
module.exports = (config) => {
const app = express();
const server = http.createServer(app);
notifier.connect(server);
app.use(routes(notifier));
return server;
};
import React, { useEffect, useRef, useState } from "react";
import { useParams } from "react-router-dom";
export default function LiveStorePurchases() {
let { storeId } = useParams();
const URL = "ws://127.0.0.1:4000?storeId=" + storeId;
const socket = useRef(null);
const [message, setMessage] = useState("");
const [reconnectInterval, setReconnectInterval] = useState(null);
const [intervalHandle, setIntervalHandle] = useState(null);
useEffect(() => {
connect();
return () => {
socket.current.close();
};
}, []);
useEffect(() => {
setReconnectInterval(2000);
return () => window.clearInterval(intervalHandle);
}, []);
useEffect(() => {
if (reconnectInterval === null) {
window.clearInterval(intervalHandle);
} else {
setIntervalHandle(
window.setInterval(() => {
connect();
console.log("reconnecting...");
}, reconnectInterval)
);
}
}, [reconnectInterval]);
function connect() {
socket.current = new WebSocket(URL);
socket.current.onopen = onOpen;
socket.current.onclose = onClose;
socket.current.onmessage = onMessage;
setReconnectInterval(null);
}
function onOpen(e) {
console.log("socket ready state", socket.current.readyState);
if (socket.current.readyState === 0) return;
socket.current.send(
JSON.stringify({
type: "connect",
user: Date.now(),
})
);
}
function onClose(e) {
setReconnectInterval(2000);
}
function onMessage(e) {
setMessage(e.data);
}
return (
<div
style={{
color: "red",
fontSize: "4rem",
}}
>
{message}
store: {storeId}
</div>
);
}
const url = require("url");
const { Server } = require("ws");
class NotifierService {
constructor() {
this.connections = new Map();
}
connect(server) {
this.server = new Server({ noServer: true });
this.interval = setInterval(this.checkAll.bind(this), 10000);
this.server.on("close", this.close.bind(this));
this.server.on("connection", this.add.bind(this));
server.on("upgrade", (request, socket, head) => {
console.log("ws upgrade");
const id = url.parse(request.url, true).query.storeId;
if (id) {
this.server.handleUpgrade(request, socket, head, (ws) =>
this.server.emit("connection", id, ws)
);
} else {
socket.destroy();
}
});
}
add(id, socket) {
console.log("ws add");
socket.isAlive = true;
socket.on("pong", () => (socket.isAlive = true));
socket.on("close", this.remove.bind(this, id));
this.connections.set(id, socket);
}
send(id, message) {
console.log("ws sending message");
const connection = this.connections.get(id);
if (!connection) {
console.log("none");
}
connection.send(JSON.stringify(message));
}
broadcast(message) {
console.log("ws broadcast");
this.connections.forEach((connection) =>
connection.send(JSON.stringify(message))
);
}
isAlive(id) {
return !!this.connections.get(id);
}
checkAll() {
this.connections.forEach((connection) => {
if (!connection.isAlive) {
return connection.terminate();
}
connection.isAlive = false;
connection.ping("");
});
}
remove(id) {
this.connections.delete(id);
}
close() {
clearInterval(this.interval);
}
}
module.exports = NotifierService;
const express = require("express");
const router = express.Router();
module.exports = (webSocketNotifier) => {
router.post("/newPurchase/:id/:msg", (req, res, next) => {
webSocketNotifier.send(
req.params.id,
`websocket message for ${req.params.id}: ${req.params.msg}`
);
res.status(200).send();
});
return router;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment