监听事件
有几种方法可以处理在服务器和客户端之间传输的事件。
EventEmitter 方法
在服务器端,Socket 实例扩展了 Node.js EventEmitter类。
在客户端,Socket 实例使用component-emitter库提供的事件发射器,它公开了 EventEmitter 方法的子集。
socket.on(eventName, listener)
将侦听器函数添加到名为eventName的事件的侦听器数组的末尾。
socket.on("details", (...args) => {
// ...
});
socket.once(eventName, listener)
为名为eventName的事件添加一次性监听函数
socket.once("details", (...args) => {
// ...
});
socket.off(eventName, listener)
从名为eventName的事件的侦听器数组中移除指定的侦听器。
const listener = (...args) => {
console.log(args);
}
socket.on("details", listener);
// and then later...
socket.off("details", listener);
socket.removeAllListeners([eventName])
删除所有侦听器,或指定eventName的侦听器。
// for a specific event
socket.removeAllListeners("details");
// for all events
socket.removeAllListeners();
Catch-all 侦听器
从 Socket.IO v3 开始,受EventEmitter2库启发的新 API 允许声明 Catch-all 侦听器。
此功能在客户端和服务器上均可用。
socket.onAny(listener)
添加一个监听器,当任何事件发出时将被触发。
socket.onAny((eventName, ...args) => {
// ...
});
socket.prependAny(listener)
添加一个监听器,当任何事件发出时将被触发。侦听器被添加到侦听器数组的开头。
socket.prependAny((eventName, ...args) => {
// ...
});
socket.offAny([listener])
删除所有catch-all侦听器或给定的侦听器。
const listener = (eventName, ...args) => {
console.log(eventName, args);
}
socket.onAny(listener);
// and then later...
socket.offAny(listener);
// or all listeners
socket.offAny();
验证
事件参数的验证超出了 Socket.IO 库的范围。
JS 生态系统中有许多包涵盖了这个用例,其中包括:
带有joi和acknowledgements的示例:
const Joi = require("joi");
const userSchema = Joi.object({
username: Joi.string().max(30).required(),
email: Joi.string().email().required()
});
io.on("connection", (socket) => {
socket.on("create user", (payload, callback) => {
if (typeof callback !== "function") {
// not an acknowledgement
return socket.disconnect();
}
const { error, value } = userSchema.validate(payload);
if (error) {
return callback({
status: "KO",
error
});
}
// do something with the value, and then
callback({
status: "OK"
});
});
});
错误处理
Socket.IO 库中目前没有内置的错误处理,这意味着您必须捕获任何可能在侦听器中引发的错误。
io.on("connection", (socket) => {
socket.on("list items", async (callback) => {
try {
const items = await findItems();
callback({
status: "OK",
items
});
} catch (e) {
callback({
status: "NOK"
});
}
});
});
在服务器端,使用EventEmitter.captureRejections = true
(实验性,请参见此处)也可能很有趣,具体取决于您的用例。
require("events").captureRejections = true;
io.on("connection", (socket) => {
socket.on("list products", async () => {
const products = await findProducts();
socket.emit("products", products);
});
socket[Symbol.for('nodejs.rejection')] = (err) => {
socket.emit("error", err);
};
});