客戶端 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
以供後續呼叫,除非 multiplex
選項傳遞為 false
。傳遞此選項等同於傳遞 "force new connection": true
或 forceNew: true
。
會傳回新的 Socket
實例,其命名空間由 URL 中的路徑名稱指定,預設為 /
。例如,如果 url
為 http://localhost/users
,將會建立傳輸連線至 http://localhost
,並建立 Socket.IO 連線至 /users
。
也可以提供查詢參數,透過 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"
}
});
可在此處找到可用選項的完整清單 here。
Manager


Manager
管理 Engine.IO client 實例,這是建立與伺服器連線的低階引擎(使用 WebSocket 或 HTTP 長輪詢等傳輸方式)。
Manager
處理重新連線邏輯。
單一 Manager
可供多個 Sockets 使用。您可以在 這裡 找到有關此多工處理功能的更多資訊。
請注意,在多數情況下,您不會直接使用 Manager,而是使用 Socket 實例。
建構函式
new Manager(url[, options])
可在此處找到可用選項的完整清單 here。
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'
error
<Error>
錯誤物件
在連線錯誤時觸發。
socket.io.on("error", (error) => {
// ...
});
事件:'ping'
從伺服器收到 ping 封包時觸發。
socket.io.on("ping", () => {
// ...
});
事件:'reconnect'
attempt
<數字>
重新連線嘗試次數
在成功重新連線時觸發。
socket.io.on("reconnect", (attempt) => {
// ...
});
事件:'reconnect_attempt'
attempt
<數字>
重新連線嘗試次數
在嘗試重新連線時觸發。
socket.io.on("reconnect_attempt", (attempt) => {
// ...
});
事件:'reconnect_error'
error
<Error>
錯誤物件
在重新連線嘗試錯誤時觸發。
socket.io.on("reconnect_error", (error) => {
// ...
});
事件:'reconnect_failed'
在無法於 reconnectionAttempts
內重新連線時觸發。
socket.io.on("reconnect_failed", () => {
// ...
});
方法
manager.connect([callback])
manager.open([callback]) 的同義詞。
manager.open([callback])
如果管理員以 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
是用於與伺服器互動的基本類別。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'
error
<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 | ✅ 是 |
傳輸中斷 | 連線已中斷(例如:使用者已失去連線,或網路已從 WiFi 變更為 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 是否會自動嘗試重新連線。
此屬性可在連線失敗後使用
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
socket 目前是否已連線至伺服器。
const socket = io();
console.log(socket.connected); // false
socket.on("connect", () => {
console.log(socket.connected); // true
});
socket.disconnected
socket 目前是否已中斷與伺服器的連線。
const socket = io();
console.log(socket.disconnected); // true
socket.on("connect", () => {
console.log(socket.disconnected); // false
});
socket.id
socket 會話的唯一識別碼。在觸發 connect
事件後設定,並在 reconnect
事件後更新。
const socket = io();
console.log(socket.id); // undefined
socket.on("connect", () => {
console.log(socket.id); // "G5p5..."
});
id
屬性是一個臨時識別碼,不應在應用程式中使用(或僅用於除錯目的),因為
- 此識別碼會在每次重新連線後重新產生(例如當 WebSocket 連線中斷,或當使用者重新整理頁面時)
- 兩個不同的瀏覽器分頁會有兩個不同的識別碼
- 伺服器上沒有為特定識別碼儲存訊息佇列(亦即,如果客戶端中斷連線,伺服器傳送至此識別碼的訊息會遺失)
請改用一般會話識別碼(透過 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
手動連接 socket。
const socket = io({
autoConnect: false
});
// ...
socket.connect();
也可以用於手動重新連接
socket.on("disconnect", () => {
socket.connect();
});
socket.disconnect()
新增於 v1.0.0
- 傳回
<Socket>
手動中斷 socket 連線。在此情況下,socket 將不會嘗試重新連接。
關聯的中斷原因
- 用戶端:
"io client disconnect"
- 伺服器端:
"client namespace disconnect"
如果這是 Manager 的最後一個 active Socket 實例,低階連線將會關閉。
socket.emit(eventName[, ...args][, ack])
eventName
<string>
|<symbol>
args
<any[]>
ack
<Function>
- 傳回
true
發射事件至由字串名稱識別的 socket。可以包含任何其他參數。所有可序列化資料結構都受支援,包括 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 中新增
eventName
<string>
|<symbol>
args
any[]
- 傳回
Promise<any>
發射事件並預期從伺服器取得確認的 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
});
});
不支援 Promises 的環境將需要加入 polyfill 才能使用此功能。
socket.listeners(eventName)
繼承自 EventEmitter 類別。
eventName
<string>
|<symbol>
- 傳回
<Function[]>
傳回名為 eventName
的事件的監聽器陣列。
socket.on("my-event", () => {
// ...
});
console.log(socket.listeners("my-event")); // prints [ [Function] ]
socket.listenersAny()
新增於 v3.0.0
- 傳回
<Function[]>
傳回已註冊的萬用監聽器清單。
const listeners = socket.listenersAny();
socket.listenersAnyOutgoing()
新增於 v4.5.0
- 傳回
<Function[]>
傳回已註冊的萬用監聽器清單,用於傳送封包。
const listeners = socket.listenersAnyOutgoing();
socket.off([eventName][, listener])
繼承自 EventEmitter 類別。
eventName
<string>
|<symbol>
listener
<Function>
- 傳回
<Socket>
從名為 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
listener
<Function>
移除先前註冊的監聽器。如果未提供監聽器,則會移除所有萬用監聽器。
const myListener = () => { /* ... */ };
socket.onAny(myListener);
// then, later
socket.offAny(myListener);
socket.offAny();
socket.offAnyOutgoing([listener])
新增於 v4.5.0
listener
<Function>
移除先前註冊的監聽器。如果未提供監聽器,則會移除所有萬用監聽器。
const myListener = () => { /* ... */ };
socket.onAnyOutgoing(myListener);
// remove a single listener
socket.offAnyOutgoing(myListener);
// remove all listeners
socket.offAnyOutgoing();
socket.on(eventName, callback)
繼承自 EventEmitter 類別。
eventName
<string>
|<symbol>
listener
<Function>
- 傳回
<Socket>
為指定的事件註冊新的處理常式。
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
callback
<函式>
註冊新的萬用監聽器。
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
callback
<函式>
註冊新的萬用監聽器,用於傳送封包。
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
<string>
|<symbol>
listener
<Function>
- 傳回
<Socket>
為名為 eventName
的事件新增一次性的 listener
函式。下次觸發 eventName
時,此監聽器會被移除,然後呼叫。
socket.once("my-event", () => {
// ...
});
socket.open()
新增於 v1.0.0
socket.connect() 的同義詞。
socket.prependAny(callback)
新增於 v3.0.0
callback
<函式>
註冊新的萬用監聽器。監聽器會新增至監聽器陣列的開頭。
socket.prependAny((event, ...args) => {
console.log(`got ${event}`);
});
socket.prependAnyOutgoing(callback)
新增於 v4.5.0
callback
<函式>
註冊新的萬用監聽器,用於監聽傳送封包。監聽器會新增至監聽器陣列的開頭。
socket.prependAnyOutgoing((event, ...args) => {
console.log(`got ${event}`);
});
socket.send([...args][, ack])
args
<any[]>
ack
<Function>
- 傳回
<Socket>
傳送 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
設定後續事件發射的修改器,表示如果發生下列情況,封包可能會被捨棄:
- socket 未連線
- 底層傳輸無法寫入(例如,當 HTTP 長輪詢模式中已有正在執行的
POST
要求)
socket.volatile.emit(/* ... */); // the server may or may not receive it