Прослушивание событий
Существует несколько способов обработки событий, передаваемых между сервером и клиентом.
Методы EventEmitter
На стороне сервера экземпляр Socket расширяет класс Node.js EventEmitter.
На стороне клиента экземпляр Socket использует эмиттер событий, предоставленный библиотекой component-emitter, которая экспонирует подмножество методов EventEmitter.
socket.on(eventName, listener)
Добавляет функцию listener в конец массива слушателей для события с именем eventName.
socket.on("details", (...args) => {
// ...
}); |
socket.once(eventName, listener)
Добавляет функцию одноразового listener для события с именем eventName
socket.once("details", (...args) => {
// ...
}); |
socket.off(eventName, listener)
Удаляет указанного 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(); |
Слушатели по умолчанию
Начиная с Socket.IO v3, новый API, вдохновлённый библиотекой EventEmitter2, позволяет объявлять слушателей по умолчанию.
Эта функция доступна как на клиенте, так и на сервере.
socket.onAny(listener)
Добавляет слушателя, который будет срабатывать при возникновении любого события.
socket.onAny((eventName, ...args) => {
// ...
}); |
socket.prependAny(listener)
Добавляет слушателя, который будет срабатывать при возникновении любого события. Слушатель добавляется в начало массива слушателей.
socket.prependAny((eventName, ...args) => {
// ...
}); |
socket.offAny([listener])
Удаляет всех слушателей по умолчанию или заданного слушателя.
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 и подтверждениями:
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);
};
}); |
© 2014–2021 Automattic
Licensed under the MIT License.
https://socket.io/docs/v3/listening-to-events