跳至主要内容
版本: 4.x

发送事件

有几种方法可以在服务器和客户端之间发送事件。

提示

对于 TypeScript 用户,可以为事件提供类型提示。请查看 此处.

基本 emit

Socket.IO API 借鉴了 Node.js EventEmitter,这意味着您可以在一端发出事件,并在另一端注册监听器

服务器

io.on("connection", (socket) => {
socket.emit("hello", "world");
});

客户端

socket.on("hello", (arg) => {
console.log(arg); // world
});

这在另一个方向也适用

服务器

io.on("connection", (socket) => {
socket.on("hello", (arg) => {
console.log(arg); // world
});
});

客户端

socket.emit("hello", "world");

您可以发送任意数量的参数,并且所有可序列化数据结构都受支持,包括二进制对象,如 BufferTypedArray

服务器

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" });

注意

  • Date 对象将被转换为(并接收为)它们的字符串表示形式,例如 1970-01-01T00:00:00.000Z

  • MapSet 必须手动序列化

const serializedMap = [...myMap.entries()];
const serializedSet = [...mySet.keys()];
  • 您可以使用 toJSON() 方法自定义对象的序列化

类示例

class Hero {
#hp;

constructor() {
this.#hp = 42;
}

toJSON() {
return { hp: this.#hp };
}
}

socket.emit("here's a hero", new Hero());

确认

事件很棒,但在某些情况下,您可能需要更经典的请求-响应 API。在 Socket.IO 中,此功能称为确认。

您可以将回调作为 emit() 的最后一个参数添加,并且当另一方确认事件时,将调用此回调

服务器

io.on("connection", (socket) => {
socket.on("update item", (arg1, arg2, callback) => {
console.log(arg1); // 1
console.log(arg2); // { name: "updated" }
callback({
status: "ok"
});
});
});

客户端

socket.emit("update item", "1", { name: "updated" }, (response) => {
console.log(response.status); // ok
});

带超时

从 Socket.IO v4.4.0 开始,您现在可以为每个 emit 分配超时

socket.timeout(5000).emit("my-event", (err) => {
if (err) {
// the other side did not acknowledge the event in the given delay
}
});

您也可以同时使用超时和 确认

socket.timeout(5000).emit("my-event", (err, response) => {
if (err) {
// the other side did not acknowledge the event in the given delay
} else {
console.log(response);
}
});

易失性事件

易失性事件是指在底层连接未准备好时不会发送的事件(在可靠性方面有点像 UDP)。

例如,如果您需要发送在线游戏中角色的位置(因为只有最新的值有用),这会很有趣。

socket.volatile.emit("hello", "might or might not be received");

另一个用例是在客户端未连接时丢弃事件(默认情况下,事件会缓冲直到重新连接)。

示例

服务器

io.on("connection", (socket) => {
console.log("connect");

socket.on("ping", (count) => {
console.log(count);
});
});

客户端

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