I'm using Express Typescript for my webpage's backend.
I have defined web sockets with socket.io
:
/src/index.ts
:
const initializeExpress = (): void => {
const app = express();
let http = require("http").Server(app);
let io = require("socket.io")(http, {
cors: {}
});
const socket_ids = {};
io.on("connection", function(socket: any) {
console.log("a user connected. socket.id: ", socket.id, "socket.username: ", socket.username);
socket_ids[socket.username] = socket.id;
});
const server = http.listen(3001, function() {
console.log("listening on *:3001");
});
// register middleware
io.use((socket, next) => {
socket.username = socket.handshake.auth.username;
socket.organization = socket.handshake.auth.organization;
next();
});
// sends each client something constantly
setInterval(() => {
for (const u in socket_ids){
const my_socket = io.sockets.sockets.get(socket_ids[u]);
my_socket.emit("knock", "knock-knock");
}
}, 10000);
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'build')));
app.use(addRespondToResponse);
attachPublicRoutes(app);
};
initializeExpress();
when the backend is started, I can confirm that the socket is working because I can receive the knock-knock
messages that my code emits to every client's socket.
Now, in many other files, I need to do socket.emit()
to specific clients at various places depending on the business logic. So I need to do my_socket = io.sockets.sockets.get(socket_ids[u])
.
How to maintain the socket_ids
object and the io
object globally / access it globally?
CodePudding user response:
You could implement a global state manager (which basically is just a simple javascript object with get and set methods) defined in a class which can be imported and accessed from any script. Then you attach those variables to that state.
Here's a very simple, but working version of what that could look like:
export class StateManager {
static addToState = (key, value) => {
if (!StateManager._singleton) {
StateManager._singleton = new StateManager();
}
StateManager._singleton.addToState(key, value);
};
static readFromState = (key: string) => {
if (!StateManager._singleton) {
StateManager._singleton = new StateManager();
}
return StateManager._singleton.readFromState(key);
};
private static _singleton: StateManager;
private _state: Record<string, any>;
private constructor() {
this._state = {};
}
private addToState = (key, value) => (this._state[key] = value);
private readFromState = (key) => this._state[key];
}
For usage, you would then add this to your code:
import { StateManager } from './state';
// your code where socket_id and io are set
StateManager.addToState('socket_ids', socket_id);
StateManager.addToState('io', io);
// your code where you want to retrieve the values:
const socket_ids = StateManager.readFromState('socket_ids');
See working example on Stackblitz.