跳到主要內容
版本:4.x

版本 4.6.0

2023 年 2 月 7 日

伺服器

錯誤修正

  • 將逾時方法新增至遠端 socket (#4558) (0c0eb00)
  • 類型:正確輸入帶有逾時的發射 (f3ada7d)

功能

基於承諾的確認

此提交在確認周圍新增了一些語法糖

  • emitWithAck()
try {
const responses = await io.timeout(1000).emitWithAck("some-event");
console.log(responses); // one response per client
} catch (e) {
// some clients did not acknowledge the event in the given delay
}

io.on("connection", async (socket) => {
// without timeout
const response = await socket.emitWithAck("hello", "world");

// with a specific timeout
try {
const response = await socket.timeout(1000).emitWithAck("hello", "world");
} catch (err) {
// the client did not acknowledge the event in the given delay
}
});
  • serverSideEmitWithAck()
try {
const responses = await io.timeout(1000).serverSideEmitWithAck("some-event");
console.log(responses); // one response per server (except itself)
} catch (e) {
// some servers did not acknowledge the event in the given delay
}

新增於 184f3cf

連線狀態復原

此功能允許客戶端在暫時斷線後重新連線並復原其狀態

  • id
  • 房間
  • 資料
  • 遺漏封包

用法

import { Server } from "socket.io";

const io = new Server({
connectionStateRecovery: {
// default values
maxDisconnectionDuration: 2 * 60 * 1000,
skipMiddlewares: true,
},
});

io.on("connection", (socket) => {
console.log(socket.recovered); // whether the state was recovered or not
});

以下是其運作方式

  • 伺服器在握手期間傳送一個階段 ID(與目前的 id 屬性不同,後者是公開的,可以自由分享)
  • 伺服器也會在每個封包中包含一個偏移量(新增於資料陣列的結尾,以確保向下相容性)
  • 在暫時斷線時,伺服器會儲存客戶端狀態一段時間(在適配器層級實作)
  • 在重新連線時,客戶端會傳送階段 ID 和它已處理的最後一個偏移量,而伺服器會嘗試復原狀態

記憶體內適配器已支援此功能,我們很快就會更新 Postgres 和 MongoDB 適配器。我們也會建立一個新的適配器,以 Redis Streams 為基礎,它將支援此功能。

新增於 54d5ee0

與 Express 中介軟體的相容性(實際上)

此功能在 Engine.IO 層級實作中介軟體,因為 Socket.IO 中介軟體是為了名稱空間授權而設計,且不會在傳統的 HTTP 要求/回應週期中執行。

語法

io.engine.use((req, res, next) => {
// do something

next();
});

// with express-session
import session from "express-session";

io.engine.use(session({
secret: "keyboard cat",
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));

// with helmet
import helmet from "helmet";

io.engine.use(helmet());

透過使用 allowRequest 選項和「標頭」事件可以達成解決方法,但這感覺更簡潔,而且也能用於升級要求。

新增於 24786e7

中斷連線和斷線事件中的錯誤詳細資料

disconnect 事件現在將包含有關斷線原因的更多詳細資訊。

io.on("connection", (socket) => {
socket.on("disconnect", (reason, description) => {
console.log(description);
});
});

新增於 8aa9499

自動移除空的子命名空間

此提交新增一個新的選項「cleanupEmptyChildNamespaces」。當啟用此選項(預設為停用)時,如果一個 socket 從動態命名空間斷線,且沒有其他 socket 連線到該命名空間,則會清除該命名空間,並關閉其適配器。

import { createServer } from "node:http";
import { Server } from "socket.io";

const httpServer = createServer();
const io = new Server(httpServer, {
cleanupEmptyChildNamespaces: true
});

新增於 5d9220b

新的「addTrailingSlash」選項

預設新增的尾斜線現在可以停用

import { createServer } from "node:http";
import { Server } from "socket.io";

const httpServer = createServer();
const io = new Server(httpServer, {
addTrailingSlash: false
});

在上面的範例中,用戶端可以省略尾斜線,並使用 /socket.io 取代 /socket.io/

新增於 d0fd474

效能改善

  • 廣播時預先計算 WebSocket 框架 (da2b542)

相依性

用戶端

錯誤修正

  • 類型化:不公開瀏覽器特定類型 (4d6d95e)
  • 確保 manager.socket() 傳回一個 active socket (b7dd891)
  • 類型化:正確輸入帶有逾時功能的 emits (#1570) (33e4172)

功能

新的「addTrailingSlash」選項

預設新增的尾斜線現在可以停用

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

const socket = io("https://example.com", {
addTrailingSlash: false
});

在上述範例中,要求的網址將會是 https://example.com/socket.io,而不是 https://example.com/socket.io/

新增於 21a6e12

基於承諾的確認

此提交在確認周圍新增了一些語法糖

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

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

注意:不支援承諾的環境需要新增 polyfill才能使用此功能。

新增於 47b979d

連線狀態復原

此功能允許用戶在暫時斷線後重新連線,並復原其 ID,以及接收斷線期間遺漏的封包。必須在伺服器端啟用。

socket 物件上新增一個名為 recovered 的布林屬性

socket.on("connect", () => {
console.log(socket.recovered); // whether the recovery was successful
});

新增於 54d5ee0(伺服器)和 b4e20c5(用戶端)。

重試機制

提供兩個新的選項

  • retries:最大重試次數。超過限制,封包將會被捨棄。
  • ackTimeout:等待確認時使用的預設逾時時間(毫秒)(不要與現有的 timeout 選項混淆,後者由管理員在連線期間使用)
const socket = io({
retries: 3,
ackTimeout: 10000
});

// implicit ack
socket.emit("my-event");

// explicit ack
socket.emit("my-event", (err, val) => { /* ... */ });

// custom timeout (in that case the ackTimeout is optional)
socket.timeout(5000).emit("my-event", (err, val) => { /* ... */ });

在上述所有範例中,「my-event」將會傳送最多 4 次(1 + 3),直到伺服器傳送確認。

為每個封包指定一個唯一 ID 是使用者的責任,以便在伺服器端進行重複資料刪除。

新增於 655dce9

相依性