Skip to content

Commit 7de2e87

Browse files
sebamarynissendarrachequesne
authored andcommitted
feat: allow to exclude specific rooms when broadcasting (#3789)
New syntax: ``` io.except("room1").emit(...); io.to("room1").except("room2").emit(...); socket.broadcast.except("room1").emit(...); socket.to("room1").except("room2").emit(...); ``` Related: - #3629 - #3657
1 parent 225ade0 commit 7de2e87

File tree

6 files changed

+167
-5
lines changed

6 files changed

+167
-5
lines changed

lib/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,18 @@ export class Server extends EventEmitter {
645645
return this;
646646
}
647647

648+
/**
649+
* Excludes a room when emitting.
650+
*
651+
* @param name
652+
* @return self
653+
* @public
654+
*/
655+
public except(name: Room): Server {
656+
this.sockets.except(name);
657+
return this;
658+
}
659+
648660
/**
649661
* Sends a `message` event to all clients.
650662
*

lib/namespace.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ export class Namespace extends EventEmitter {
2929
/** @private */
3030
_rooms: Set<Room> = new Set();
3131

32+
/** @private */
33+
_except: Set<Room> = new Set();
34+
3235
/** @private */
3336
_flags: any = {};
3437

@@ -123,6 +126,18 @@ export class Namespace extends EventEmitter {
123126
return this;
124127
}
125128

129+
/**
130+
* Excludes a room when emitting.
131+
*
132+
* @param name
133+
* @return self
134+
* @public
135+
*/
136+
public except(name: Room): Namespace {
137+
this._except.add(name);
138+
return this;
139+
}
140+
126141
/**
127142
* Adds a new client.
128143
*
@@ -203,14 +218,17 @@ export class Namespace extends EventEmitter {
203218

204219
const rooms = new Set(this._rooms);
205220
const flags = Object.assign({}, this._flags);
221+
const except = new Set(this._except);
206222

207223
// reset flags
208224
this._rooms.clear();
209225
this._flags = {};
226+
this._except.clear();
210227

211228
this.adapter.broadcast(packet, {
212229
rooms: rooms,
213230
flags: flags,
231+
except: except,
214232
});
215233

216234
return true;

lib/socket.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export class Socket extends EventEmitter {
9292
> = [];
9393
private flags: BroadcastFlags = {};
9494
private _rooms: Set<Room> = new Set();
95+
private _except: Set<Room> = new Set();
9596
private _anyListeners?: Array<(...args: any[]) => void>;
9697

9798
/**
@@ -166,14 +167,16 @@ export class Socket extends EventEmitter {
166167

167168
const rooms = new Set(this._rooms);
168169
const flags = Object.assign({}, this.flags);
170+
const except = new Set(this._except);
169171

170172
// reset flags
171173
this._rooms.clear();
172174
this.flags = {};
175+
this._except.clear();
173176

174177
if (rooms.size || flags.broadcast) {
175178
this.adapter.broadcast(packet, {
176-
except: new Set([this.id]),
179+
except: new Set([this.id, ...except]),
177180
rooms: rooms,
178181
flags: flags,
179182
});
@@ -208,6 +211,18 @@ export class Socket extends EventEmitter {
208211
return this;
209212
}
210213

214+
/**
215+
* Excludes a room when broadcasting.
216+
*
217+
* @param name
218+
* @return self
219+
* @public
220+
*/
221+
public except(name: Room): Socket {
222+
this._except.add(name);
223+
return this;
224+
}
225+
211226
/**
212227
* Sends a `message` event.
213228
*

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
"base64id": "~2.0.0",
5151
"debug": "~4.3.1",
5252
"engine.io": "~4.1.0",
53-
"socket.io-adapter": "~2.1.0",
53+
"socket.io-adapter": "~2.2.0",
5454
"socket.io-parser": "~4.0.3"
5555
},
5656
"devDependencies": {

test/socket.io.ts

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,57 @@ describe("socket.io", () => {
823823
});
824824
});
825825

826+
it("should exclude a specific socket when emitting", (done) => {
827+
const srv = createServer();
828+
const sio = new Server(srv);
829+
830+
const nsp = sio.of("/nsp");
831+
832+
srv.listen(() => {
833+
const socket1 = client(srv, "/nsp");
834+
const socket2 = client(srv, "/nsp");
835+
836+
socket2.on("a", () => {
837+
done(new Error("not"));
838+
});
839+
socket1.on("a", () => {
840+
done();
841+
});
842+
843+
socket2.on("connect", () => {
844+
nsp.except(socket2.id).emit("a");
845+
});
846+
});
847+
});
848+
849+
it("should exclude a specific room when emitting", (done) => {
850+
const srv = createServer();
851+
const sio = new Server(srv);
852+
853+
const nsp = sio.of("/nsp");
854+
855+
srv.listen(() => {
856+
const socket1 = client(srv, "/nsp");
857+
const socket2 = client(srv, "/nsp");
858+
859+
socket1.on("a", () => {
860+
done();
861+
});
862+
socket2.on("a", () => {
863+
done(new Error("not"));
864+
});
865+
866+
nsp.on("connection", (socket) => {
867+
socket.on("broadcast", () => {
868+
socket.join("room1");
869+
nsp.except("room1").emit("a");
870+
});
871+
});
872+
873+
socket2.emit("broadcast");
874+
});
875+
});
876+
826877
describe("dynamic namespaces", () => {
827878
it("should allow connections to dynamic namespaces with a regex", (done) => {
828879
const srv = createServer();
@@ -2222,6 +2273,72 @@ describe("socket.io", () => {
22222273
});
22232274
});
22242275
});
2276+
2277+
it("should exclude specific sockets when broadcasting", (done) => {
2278+
const srv = createServer();
2279+
const sio = new Server(srv);
2280+
2281+
srv.listen(() => {
2282+
const socket1 = client(srv, { multiplex: false });
2283+
const socket2 = client(srv, { multiplex: false });
2284+
const socket3 = client(srv, { multiplex: false });
2285+
2286+
socket2.on("a", () => {
2287+
done(new Error("not"));
2288+
});
2289+
socket3.on("a", () => {
2290+
done(new Error("not"));
2291+
});
2292+
socket1.on("a", () => {
2293+
done();
2294+
});
2295+
2296+
sio.on("connection", (socket) => {
2297+
socket.on("exclude", (id) => {
2298+
socket.broadcast.except(id).emit("a");
2299+
});
2300+
});
2301+
2302+
socket2.on("connect", () => {
2303+
socket3.emit("exclude", socket2.id);
2304+
});
2305+
});
2306+
});
2307+
2308+
it("should exclude a specific room when broadcasting", (done) => {
2309+
const srv = createServer();
2310+
const sio = new Server(srv);
2311+
2312+
srv.listen(() => {
2313+
const socket1 = client(srv, { multiplex: false });
2314+
const socket2 = client(srv, { multiplex: false });
2315+
const socket3 = client(srv, { multiplex: false });
2316+
2317+
socket2.on("a", () => {
2318+
done(new Error("not"));
2319+
});
2320+
socket3.on("a", () => {
2321+
done(new Error("not"));
2322+
});
2323+
socket1.on("a", () => {
2324+
done();
2325+
});
2326+
2327+
sio.on("connection", (socket) => {
2328+
socket.on("join", (room, cb) => {
2329+
socket.join(room);
2330+
cb();
2331+
});
2332+
socket.on("broadcast", () => {
2333+
socket.broadcast.except("room1").emit("a");
2334+
});
2335+
});
2336+
2337+
socket2.emit("join", "room1", () => {
2338+
socket3.emit("broadcast");
2339+
});
2340+
});
2341+
});
22252342
});
22262343

22272344
describe("middleware", () => {

0 commit comments

Comments
 (0)