Skip to content

Commit 61ee20b

Browse files
committed
feat: leave multiple rooms at once
1 parent 5474363 commit 61ee20b

File tree

4 files changed

+58
-12
lines changed

4 files changed

+58
-12
lines changed

packages/socket.io-adapter/lib/in-memory-adapter.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,17 +104,30 @@ export class Adapter extends EventEmitter {
104104
}
105105

106106
/**
107-
* Removes a socket from a room.
107+
* Removes a socket from one or multiple rooms.
108108
*
109-
* @param {SocketId} id the socket id
110-
* @param {Room} room the room name
109+
* @param {SocketId} id the socket id
110+
* @param {Room|Set<Room>} rooms the room name or a set of rooms
111111
*/
112-
public del(id: SocketId, room: Room): Promise<void> | void {
113-
if (this.sids.has(id)) {
114-
this.sids.get(id).delete(room);
112+
public del(id: SocketId, rooms: Room | Set<Room>): Promise<void> | void {
113+
const roomsToRemove = rooms instanceof Set ? rooms : new Set<Room>([rooms]);
114+
const socketRooms = this.sids.get(id);
115+
116+
if (!socketRooms) {
117+
for (const room of roomsToRemove) {
118+
this._del(room, id);
119+
}
120+
return;
115121
}
116122

117-
this._del(room, id);
123+
for (const room of roomsToRemove) {
124+
socketRooms.delete(room);
125+
this._del(room, id);
126+
}
127+
128+
if (socketRooms.size === 0) {
129+
this.sids.delete(id);
130+
}
118131
}
119132

120133
private _del(room: Room, id: SocketId) {

packages/socket.io-adapter/test/index.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,19 @@ describe("socket.io-adapter", () => {
2626
expect(adapter.sids.has("s2")).to.be(false);
2727
});
2828

29+
it("should remove multiple rooms with a single call", () => {
30+
const adapter = new Adapter({ server: { encoder: null } });
31+
adapter.addAll("s1", new Set(["r1", "r2", "r3"]));
32+
33+
adapter.del("s1", new Set(["r1", "r3"]));
34+
35+
expect(adapter.rooms.has("r1")).to.be(false);
36+
expect(adapter.rooms.has("r3")).to.be(false);
37+
expect(adapter.rooms.has("r2")).to.be(true);
38+
expect(adapter.sids.get("s1").size).to.be(1);
39+
expect(adapter.sids.get("s1").has("r2")).to.be(true);
40+
});
41+
2942
it("should return a list of sockets", async () => {
3043
const adapter = new Adapter({
3144
server: { encoder: null },

packages/socket.io/lib/socket.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -476,16 +476,19 @@ export class Socket<
476476
* socket.leave("room1");
477477
*
478478
* // leave multiple rooms
479-
* socket.leave("room1").leave("room2");
479+
* socket.leave(["room1", "room2"]);
480480
* });
481481
*
482-
* @param {String} room
482+
* @param {String|Array} rooms - room or array of rooms
483483
* @return a Promise or nothing, depending on the adapter
484484
*/
485-
public leave(room: string): Promise<void> | void {
486-
debug("leave room %s", room);
485+
public leave(rooms: Room | Array<Room>): Promise<void> | void {
486+
debug("leave room %s", rooms);
487487

488-
return this.adapter.del(this.id, room);
488+
return this.adapter.del(
489+
this.id,
490+
new Set(Array.isArray(rooms) ? rooms : [rooms]),
491+
);
489492
}
490493

491494
/**

packages/socket.io/test/socket.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,23 @@ describe("socket", () => {
941941
});
942942
});
943943

944+
it("should leave multiple rooms at once", (done) => {
945+
const io = new Server(0);
946+
const client = createClient(io, "/");
947+
948+
io.on("connection", (socket) => {
949+
Promise.resolve(socket.join(["room1", "room2"]))
950+
.then(() => Promise.resolve(socket.leave(["room1", "room2"])))
951+
.then(() => {
952+
const adapter = io.of("/").adapter;
953+
expect(adapter.rooms.has("room1")).to.be(false);
954+
expect(adapter.rooms.has("room2")).to.be(false);
955+
success(done, io, client);
956+
})
957+
.catch(done);
958+
});
959+
});
960+
944961
describe("onAny", () => {
945962
it("should call listener", (done) => {
946963
const io = new Server(0);

0 commit comments

Comments
 (0)