发送事件
有几种方法可以在服务器和客户端之间发送事件。
提示
对于 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");
您可以发送任意数量的参数,并且支持所有可序列化的数据结构,包括像Buffer 或 TypedArray这样的二进制对象。
服务器
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" });
笔记:
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 开始,您现在可以为每个发射分配超时:
socket.timeout(5000).emit("my-event", (err) => {
if (err) {
// the other side did not acknowledge the event in the given delay
}
});
You can also use both a timeout and an acknowledgement:
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