Created
December 16, 2021 17:54
-
-
Save DashBarkHuss/cccbf407c11560f8d21bceab021f37c0 to your computer and use it in GitHub Desktop.
Sample WebSocket node.js, react, express.js with broadcast and send happening in a route
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
// I moved POST /newPurchase to routes.js in order | |
// to demonstrate how the notifier instance can be | |
// passed around to different routes | |
app.use(routes(notifier)); | |
return server; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useEffect, 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 [ws, setWs] = useState(new WebSocket(URL)); | |
useEffect(() => { | |
ws.onopen = (e) => { | |
newFunction(e); | |
function newFunction(e) { | |
alert("WebSocket Connected"); | |
} | |
}; | |
ws.onmessage = (e) => { | |
const message = e.data; | |
alert(message); | |
}; | |
return () => { | |
ws.onclose = () => { | |
alert("WebSocket Disconnected"); | |
setWs(new WebSocket(URL)); | |
}; | |
}; | |
}, [ws.onmessage, ws.onopen, ws.onclose, ws, URL]); | |
return ( | |
<div | |
style={{ | |
color: "red", | |
fontSize: "4rem", | |
}} | |
> | |
store: {storeId} | |
</div> | |
); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
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; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const express = require("express"); | |
const router = express.Router(); | |
module.exports = (webSocketNotifier) => { | |
router.post("/newPurchase/:id", (req, res, next) => { | |
webSocketNotifier.send(req.params.id, "purchase made"); | |
res.status(200).send(); | |
}); | |
return router; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const server = require("../server/app")(); | |
const port = process.env.PORT || "4000"; | |
server | |
.listen(port) | |
.on("listening", () => | |
console.log("info", `HTTP server listening on port ${port}`) | |
); | |
module.exports = server; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment