express/typescript: 在服务器端,如何创建一个全局变量来存储多个套接字?
express/typescript: on the server side, how to create a global variable to store multiple sockets?
我在网页后端使用 Express + Typescript。
我已经用 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();
当后端启动时,我可以确认套接字正在工作,因为我可以接收到我的代码发送到每个客户端套接字的 knock-knock
消息。
现在,在许多其他文件中,我需要根据业务逻辑在不同位置对特定客户端执行 socket.emit()
。所以我需要做 my_socket = io.sockets.sockets.get(socket_ids[u])
.
如何全局维护socket_ids
对象和io
对象/全局访问它?
您可以实现在 class 中定义的全局状态管理器(它基本上只是一个具有 get 和 set 方法的简单 javascript 对象),它可以从任何脚本导入和访问。然后将这些变量附加到该状态。
这是一个非常简单但可行的版本:
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];
}
为了便于使用,您可以将其添加到您的代码中:
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');
参见 Stackblitz 上的工作示例。
我在网页后端使用 Express + Typescript。
我已经用 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();
当后端启动时,我可以确认套接字正在工作,因为我可以接收到我的代码发送到每个客户端套接字的 knock-knock
消息。
现在,在许多其他文件中,我需要根据业务逻辑在不同位置对特定客户端执行 socket.emit()
。所以我需要做 my_socket = io.sockets.sockets.get(socket_ids[u])
.
如何全局维护socket_ids
对象和io
对象/全局访问它?
您可以实现在 class 中定义的全局状态管理器(它基本上只是一个具有 get 和 set 方法的简单 javascript 对象),它可以从任何脚本导入和访问。然后将这些变量附加到该状态。
这是一个非常简单但可行的版本:
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];
}
为了便于使用,您可以将其添加到您的代码中:
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');
参见 Stackblitz 上的工作示例。