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

客户端 API

IO

io 方法绑定到独立构建中的全局范围

<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io();
</script>

自版本 4.3.0 起,还提供 ESM 包

<script type="module">
import { io } from "https://cdn.socket.io/4.7.5/socket.io.esm.min.js";

const socket = io();
</script>

使用 导入映射

<script type="importmap">
{
"imports": {
"socket.io-client": "https://cdn.socket.io/4.7.5/socket.io.esm.min.js"
}
}
</script>

<script type="module">
import { io } from "socket.io-client";

const socket = io();
</script>

否则,在所有其他情况下(使用某些构建工具,在 Node.js 或 React Native 中),它可以从 socket.io-client 包中导入

// ES modules
import { io } from "socket.io-client";

// CommonJS
const { io } = require("socket.io-client");

io.protocol

协议修订号(当前:5)。

协议定义了客户端和服务器之间交换的数据包格式。客户端和服务器都必须使用相同的修订版才能相互理解。

您可以在 此处 找到更多信息。

io([url][, options])

为给定 URL 创建新的 Manager,并尝试为后续调用重用现有 Manager,除非使用 false 传递 multiplex 选项。传递此选项等同于传递 "force new connection": trueforceNew: true

为 URL 中路径名指定的命名空间返回新的 Socket 实例,默认为 /。例如,如果 urlhttp://localhost/users,则将建立到 http://localhost 的传输连接,并将建立到 /users 的 Socket.IO 连接。

也可以提供查询参数,使用 query 选项或直接在 url 中提供(例如:http://localhost/users?token=abc)。

为了理解幕后发生的事情,以下示例

import { io } from "socket.io-client";

const socket = io("ws://example.com/my-namespace", {
reconnectionDelayMax: 10000,
auth: {
token: "123"
},
query: {
"my-key": "my-value"
}
});

是简短版本

import { Manager } from "socket.io-client";

const manager = new Manager("ws://example.com", {
reconnectionDelayMax: 10000,
query: {
"my-key": "my-value"
}
});

const socket = manager.socket("/my-namespace", {
auth: {
token: "123"
}
});

可以在 此处 找到所有可用选项的完整列表。

Manager

Manager in the class diagram for the clientManager in the class diagram for the client

Manager 管理 Engine.IO 客户端 实例,它是建立与服务器连接的低级引擎(通过使用 WebSocket 或 HTTP 长轮询等传输)。

Manager 处理重新连接逻辑。

单个 Manager 可以被多个 Sockets 使用。您可以在 此处 找到有关此多路复用功能的更多信息。

请注意,在大多数情况下,您不会直接使用 Manager,而是使用 Socket 实例。

构造函数

new Manager(url[, options])

可以在 此处 找到所有可用选项的完整列表。

import { Manager } from "socket.io-client";

const manager = new Manager("https://example.com");

const socket = manager.socket("/"); // main namespace
const adminSocket = manager.socket("/admin"); // admin namespace

事件

事件: 'error'

在连接错误时触发。

socket.io.on("error", (error) => {
// ...
});

事件: 'ping'

从服务器收到 ping 数据包时触发。

socket.io.on("ping", () => {
// ...
});

事件: 'reconnect'

  • attempt <number> 重新连接尝试次数

在成功重新连接时触发。

socket.io.on("reconnect", (attempt) => {
// ...
});

事件: 'reconnect_attempt'

  • attempt <number> 重新连接尝试次数

在尝试重新连接时触发。

socket.io.on("reconnect_attempt", (attempt) => {
// ...
});

事件: 'reconnect_error'

在重新连接尝试错误时触发。

socket.io.on("reconnect_error", (error) => {
// ...
});

事件: 'reconnect_failed'

在无法在 reconnectionAttempts 内重新连接时触发。

socket.io.on("reconnect_failed", () => {
// ...
});

方法

manager.connect([callback])

manager.open([callback]) 的同义词。

manager.open([callback])

如果 manager 使用 autoConnect 初始化为 false,则启动新的连接尝试。

callback 参数是可选的,将在尝试失败/成功后调用。

import { Manager } from "socket.io-client";

const manager = new Manager("https://example.com", {
autoConnect: false
});

const socket = manager.socket("/");

manager.open((err) => {
if (err) {
// an error has occurred
} else {
// the connection was successfully established
}
});

manager.reconnection([value])

设置 reconnection 选项,或者如果未传递参数,则返回它。

manager.reconnectionAttempts([value])

设置 reconnectionAttempts 选项,或者如果未传递参数,则返回它。

manager.reconnectionDelay([value])

设置 reconnectionDelay 选项,或者如果未传递参数,则返回它。

manager.reconnectionDelayMax([value])

设置 reconnectionDelayMax 选项,或者如果未传递参数,则返回它。

manager.socket(nsp, options)

为给定命名空间创建一个新的 Socket。仅从 options 对象中读取 auth{ auth: {key: "value"} })。其他键将被忽略,应在实例化 new Manager(nsp, options) 时传递。

manager.timeout([value])

设置 timeout 选项,或者如果未传递参数,则返回它。

Socket

Socket in the class diagram for the clientSocket in the class diagram for the client

Socket 是与服务器交互的基本类。Socket 属于某个 命名空间(默认情况下为 /),并使用底层的 Manager 进行通信。

Socket 本质上是一个 EventEmitter,它通过网络向服务器发送事件,并从服务器接收事件。

socket.emit("hello", { a: "b", c: [] });

socket.on("hey", (...args) => {
// ...
});

可以在 此处 找到更多信息。

事件

事件: 'connect'

此事件在 Socket 实例连接重新连接时触发。

socket.on("connect", () => {
// ...
});
注意

事件处理程序不应在 connect 处理程序本身中注册,因为每次 socket 实例重新连接时都会注册一个新的处理程序

错误 ⚠️

socket.on("connect", () => {
socket.on("data", () => { /* ... */ });
});

正确 👍

socket.on("connect", () => {
// ...
});

socket.on("data", () => { /* ... */ });

事件: 'connect_error'

此事件在连接失败时触发。

原因自动重新连接?
无法建立低级连接(临时故障)✅ 是
服务器在 中间件函数 中拒绝了连接❌ 否

socket.active 属性指示 socket 是否会在短暂的 随机延迟 后自动尝试重新连接

socket.on("connect_error", (error) => {
if (socket.active) {
// temporary failure, the socket will automatically try to reconnect
} else {
// the connection was denied by the server
// in that case, `socket.connect()` must be manually called in order to reconnect
console.log(error.message);
}
});

事件: 'disconnect'

  • reason <string>
  • details <DisconnectDetails>

此事件在断开连接时触发。

socket.on("disconnect", (reason, details) => {
// ...
});

以下是可能的理由列表

原因描述自动重新连接?
io 服务器断开连接服务器使用 socket.disconnect() 强制断开了 socket 连接❌ 否
io 客户端断开连接使用 socket.disconnect() 手动断开了 socket 连接❌ 否
ping 超时服务器在 pingInterval + pingTimeout 范围内未发送 PING✅ 是
传输关闭连接已关闭(例如:用户已断开连接,或网络从 Wi-Fi 切换到 4G)。✅ 是
传输错误连接遇到错误(例如:服务器在 HTTP 长轮询周期中被终止)。✅ 是

socket.active 属性指示 socket 是否会在短暂的 随机延迟 后自动尝试重新连接

socket.on("disconnect", (reason) => {
if (socket.active) {
// temporary disconnection, the socket will automatically try to reconnect
} else {
// the connection was forcefully closed by the server or the client itself
// in that case, `socket.connect()` must be manually called in order to reconnect
console.log(reason);
}
});

属性

socket.active

是否自动尝试重新连接。

此属性可以在连接失败后使用

socket.on("connect_error", (error) => {
if (socket.active) {
// temporary failure, the socket will automatically try to reconnect
} else {
// the connection was denied by the server
// in that case, `socket.connect()` must be manually called in order to reconnect
console.log(error.message);
}
});

或断开连接后使用

socket.on("disconnect", (reason) => {
if (socket.active) {
// temporary disconnection, the socket will automatically try to reconnect
} else {
// the connection was forcefully closed by the server or the client itself
// in that case, `socket.connect()` must be manually called in order to reconnect
console.log(reason);
}
});

socket.connected

套接字当前是否已连接到服务器。

const socket = io();

console.log(socket.connected); // false

socket.on("connect", () => {
console.log(socket.connected); // true
});

socket.disconnected

套接字当前是否已断开与服务器的连接。

const socket = io();

console.log(socket.disconnected); // true

socket.on("connect", () => {
console.log(socket.disconnected); // false
});

socket.id

套接字会话的唯一标识符。在触发 connect 事件后设置,并在 reconnect 事件后更新。

const socket = io();

console.log(socket.id); // undefined

socket.on("connect", () => {
console.log(socket.id); // "G5p5..."
});
注意

id 属性是一个短暂的 ID,不应在您的应用程序中使用(或仅用于调试目的),因为

  • 此 ID 在每次重新连接后都会重新生成(例如,当 WebSocket 连接断开时,或当用户刷新页面时)。
  • 两个不同的浏览器标签将具有两个不同的 ID。
  • 服务器上没有为给定 ID 存储消息队列(即,如果客户端断开连接,则从服务器发送到此 ID 的消息将丢失)。

请改用常规会话 ID(通过 cookie 发送,或存储在 localStorage 中并发送到 auth 负载中)。

另请参见

socket.io

对底层 Manager 的引用。

socket.on("connect", () => {
const engine = socket.io.engine;
console.log(engine.transport.name); // in most cases, prints "polling"

engine.once("upgrade", () => {
// called when the transport is upgraded (i.e. from HTTP long-polling to WebSocket)
console.log(engine.transport.name); // in most cases, prints "websocket"
});

engine.on("packet", ({ type, data }) => {
// called for each packet received
});

engine.on("packetCreate", ({ type, data }) => {
// called for each packet sent
});

engine.on("drain", () => {
// called when the write buffer is drained
});

engine.on("close", (reason) => {
// called when the underlying connection is closed
});
});

socket.recovered

在 v4.6.0 中添加

连接状态是否在上次重新连接期间成功恢复。

socket.on("connect", () => {
if (socket.recovered) {
// any event missed during the disconnection period will be received now
} else {
// new or unrecoverable session
}
});

有关此功能的更多信息,请 点击这里

方法

socket.close()

在 v1.0.0 中添加

socket.disconnect() 的同义词。

socket.compress(value)

为后续事件发射设置一个修饰符,指示事件数据仅在值为 true 时才压缩。默认情况下,如果您不调用此方法,则为 true

socket.compress(false).emit("an event", { some: "data" });

socket.connect()

在 v1.0.0 中添加

  • 返回值 Socket

手动连接套接字。

const socket = io({
autoConnect: false
});

// ...
socket.connect();

它也可以用于手动重新连接

socket.on("disconnect", () => {
socket.connect();
});

socket.disconnect()

在 v1.0.0 中添加

手动断开套接字连接。在这种情况下,套接字将不会尝试重新连接。

关联的断开连接原因

  • 客户端:"io client disconnect"
  • 服务器端:"client namespace disconnect"

如果这是 Manager 的最后一个活动 Socket 实例,则低级连接将被关闭。

socket.emit(eventName[, ...args][, ack])

向由字符串名称标识的套接字发出事件。可以包含任何其他参数。所有可序列化数据结构都受支持,包括 Buffer

socket.emit("hello", "world");
socket.emit("with-binary", 1, "2", { 3: "4", 5: Buffer.from([6, 7, 8]) });

ack 参数是可选的,将使用服务器答案进行调用。

客户端

socket.emit("hello", "world", (response) => {
console.log(response); // "got it"
});

服务器

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

socket.emitWithAck(eventName[, ...args])

在 v4.6.0 中添加

基于 Promise 的发出事件并期望服务器确认的版本

// without timeout
const response = await socket.emitWithAck("hello", "world");

// with a specific timeout
try {
const response = await socket.timeout(10000).emitWithAck("hello", "world");
} catch (err) {
// the server did not acknowledge the event in the given delay
}

上面的示例等效于

// without timeout
socket.emit("hello", "world", (val) => {
// ...
});

// with a specific timeout
socket.timeout(10000).emit("hello", "world", (err, val) => {
// ...
});

在接收端

io.on("connection", (socket) => {
socket.on("hello", (arg1, callback) => {
callback("got it"); // only one argument is expected
});
});
注意

不支持 Promise 的环境需要添加 polyfill 才能使用此功能。

socket.listeners(eventName)

继承自 EventEmitter 类

返回名为 eventName 的事件的监听器数组。

socket.on("my-event", () => {
// ...
});

console.log(socket.listeners("my-event")); // prints [ [Function] ]

socket.listenersAny()

在 v3.0.0 中添加

返回已注册的通配符监听器列表。

const listeners = socket.listenersAny();

socket.listenersAnyOutgoing()

在 v4.5.0 中添加

返回已注册的用于出站数据包的通配符监听器列表。

const listeners = socket.listenersAnyOutgoing();

socket.off([eventName][, listener])

继承自 EventEmitter 类

从名为 eventName 的事件的监听器数组中删除指定的 listener

const myListener = () => {
// ...
}

socket.on("my-event", myListener);

// then later
socket.off("my-event", myListener);

listener 参数也可以省略

// remove all listeners for that event
socket.off("my-event");

// remove all listeners for all events
socket.off();

socket.offAny([listener])

在 v3.0.0 中添加

删除先前注册的监听器。如果没有提供监听器,则删除所有通配符监听器。

const myListener = () => { /* ... */ };

socket.onAny(myListener);

// then, later
socket.offAny(myListener);

socket.offAny();

socket.offAnyOutgoing([listener])

在 v4.5.0 中添加

删除先前注册的监听器。如果没有提供监听器,则删除所有通配符监听器。

const myListener = () => { /* ... */ };

socket.onAnyOutgoing(myListener);

// remove a single listener
socket.offAnyOutgoing(myListener);

// remove all listeners
socket.offAnyOutgoing();

socket.on(eventName, callback)

继承自 EventEmitter 类

为给定事件注册一个新的处理程序。

socket.on("news", (data) => {
console.log(data);
});

// with multiple arguments
socket.on("news", (arg1, arg2, arg3, arg4) => {
// ...
});
// with callback
socket.on("news", (cb) => {
cb(0);
});

socket.onAny(callback)

在 v3.0.0 中添加

注册一个新的通配符监听器。

socket.onAny((event, ...args) => {
console.log(`got ${event}`);
});
注意

确认 不会被通配符监听器捕获。

socket.emit("foo", (value) => {
// ...
});

socket.onAnyOutgoing(() => {
// triggered when the event is sent
});

socket.onAny(() => {
// not triggered when the acknowledgement is received
});

socket.onAnyOutgoing(callback)

在 v4.5.0 中添加

为出站数据包注册一个新的通配符监听器。

socket.onAnyOutgoing((event, ...args) => {
console.log(`got ${event}`);
});
注意

确认 不会被通配符监听器捕获。

socket.on("foo", (value, callback) => {
callback("OK");
});

socket.onAny(() => {
// triggered when the event is received
});

socket.onAnyOutgoing(() => {
// not triggered when the acknowledgement is sent
});

socket.once(eventName, callback)

继承自 EventEmitter 类

为名为 eventName 的事件添加一次性 listener 函数。下次触发 eventName 时,此监听器将被删除,然后调用。

socket.once("my-event", () => {
// ...
});

socket.open()

在 v1.0.0 中添加

socket.connect() 的同义词。

socket.prependAny(callback)

在 v3.0.0 中添加

注册一个新的通配符监听器。监听器被添加到监听器数组的开头。

socket.prependAny((event, ...args) => {
console.log(`got ${event}`);
});

socket.prependAnyOutgoing(callback)

在 v4.5.0 中添加

为出站数据包注册一个新的通配符监听器。监听器被添加到监听器数组的开头。

socket.prependAnyOutgoing((event, ...args) => {
console.log(`got ${event}`);
});

socket.send([...args][, ack])

发送 message 事件。请参阅 socket.emit(eventName[, ...args][, ack])

socket.timeout(value)

在 v4.4.0 中添加

为后续事件发射设置一个修饰符,指示当给定毫秒数过去而没有收到服务器的确认时,回调将使用错误进行调用

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

标志

标志:'volatile'

在 v3.0.0 中添加

为后续事件发射设置一个修饰符,指示如果

  • 套接字未连接
  • 低级传输不可写(例如,当 HTTP 长轮询模式中已在运行 POST 请求时)
socket.volatile.emit(/* ... */); // the server may or may not receive it