Отправка событий
Существует несколько способов отправки событий между сервером и клиентом.
Основные отправки
API Socket.IO вдохновлен EventEmitter из Node.js EventEmitter, что означает, что вы можете отправлять события с одной стороны и регистрировать слушателей с другой:
// server-side
io.on("connection", (socket) => {
socket.emit("hello", "world");
});
// client-side
socket.on("hello", (arg) => {
console.log(arg); // world
}); |
Это также работает в обратном направлении:
// server-side
io.on("connection", (socket) => {
socket.on("hello", (arg) => {
console.log(arg); // world
});
});
// client-side
socket.emit("hello", "world"); |
Вы можете отправлять любое количество аргументов, и поддерживаются все сериализуемые структуры данных, включая двоичные объекты, такие как Buffer или TypedArray.
// server-side
io.on("connection", (socket) => {
socket.emit("hello", 1, "2", { 3: '4', 5: Buffer.from([6]) });
});
// client-side
socket.on("hello", (arg1, arg2, arg3) => {
console.log(arg1); // 1
console.log(arg2); // "2"
console.log(arg3); // { 3: '4', 5: ArrayBuffer (1) [ 6 ] }
}); |
Не нужно выполнять JSON.stringify() над объектами, так как это будет сделано за вас.
// BAD
socket.emit("hello", JSON.stringify({ name: "John" }));
// GOOD
socket.emit("hello", { name: "John" }); |
Примечание: Map и Set не сериализуются и должны быть сериализованы вручную:
const serializedMap = [...myMap.entries()]; const serializedSet = [...mySet.keys()]; |
Подтверждения
События отлично подходят, но в некоторых случаях вам может потребоваться более классический API запроса-ответа. В Socket.IO эта функция называется подтверждениями.
Вы можете добавить обратный вызов в качестве последнего аргумента emit(), и этот обратный вызов будет вызван, как только другая сторона подтвердит событие:
// server-side
io.on("connection", (socket) => {
socket.on("update item", (arg1, arg2, callback) => {
console.log(arg1); // 1
console.log(arg2); // { name: "updated" }
callback({
status: "ok"
});
});
});
// client-side
socket.emit("update item", "1", { name: "updated" }, (response) => {
console.log(response.status); // ok
}); |
Таймауты по умолчанию не поддерживаются, но их довольно просто реализовать:
const withTimeout = (onSuccess, onTimeout, timeout) => {
let called = false;
const timer = setTimeout(() => {
if (called) return;
called = true;
onTimeout();
}, timeout);
return (...args) => {
if (called) return;
called = true;
clearTimeout(timer);
onSuccess.apply(this, args);
}
}
socket.emit("hello", 1, 2, withTimeout(() => {
console.log("success!");
}, () => {
console.log("timeout!");
}, 1000)); |
Летучие события
Летучие события — это события, которые не будут отправлены, если базовое соединение не готово (немного похоже на UDP, с точки зрения надёжности).
Это может быть интересно, например, если вам нужно отправить положение символов в онлайн-игре (поскольку только последние значения полезны).
socket.volatile.emit("hello", "might or might not be received"); |
Другой случай использования — отбрасывание событий, когда клиент не подключен (по умолчанию события буферизуются до повторного подключения).
Пример:
// server-side
io.on("connection", (socket) => {
console.log("connect");
socket.on("ping", (count) => {
console.log(count);
});
});
// client-side
let count = 0;
setInterval(() => {
socket.volatile.emit("ping", ++count);
}, 1000); |
Если вы перезапустите сервер, вы увидите в консоли:
connect 1 2 3 4 # the server is restarted, the client automatically reconnects connect 9 10 11 |
Без флага volatile, вы увидите:
connect 1 2 3 4 # the server is restarted, the client automatically reconnects and sends its buffered events connect 5 6 7 8 9 10 11 |
© 2014–2021 Automattic
Licensed under the MIT License.
https://socket.io/docs/v3/emitting-events