Skip to content

Commit 531104d

Browse files
committedMar 31, 2022
feat: add support for catch-all listeners for outgoing packets
This is similar to `onAny()`, but for outgoing packets. Syntax: ```js socket.onAnyOutgoing((event, ...args) => { console.log(event); }); ```
1 parent 8b20457 commit 531104d

File tree

3 files changed

+211
-7
lines changed

3 files changed

+211
-7
lines changed
 

‎lib/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {
2828
StrictEventEmitter,
2929
EventNames,
3030
} from "./typed-events";
31-
import { patchAdapter, restoreAdapter, serveFile } from "./uws.js";
31+
import { patchAdapter, restoreAdapter, serveFile } from "./uws";
3232

3333
const debug = debugModule("socket.io:server");
3434

‎lib/socket.ts

+115-5
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ export class Socket<
142142
private fns: Array<(event: Event, next: (err?: Error) => void) => void> = [];
143143
private flags: BroadcastFlags = {};
144144
private _anyListeners?: Array<(...args: any[]) => void>;
145+
private _anyOutgoingListeners?: Array<(...args: any[]) => void>;
145146

146147
/**
147148
* Interface to a `Client` for a given `Namespace`.
@@ -220,6 +221,7 @@ export class Socket<
220221
const flags = Object.assign({}, this.flags);
221222
this.flags = {};
222223

224+
this.notifyOutgoingListeners(packet);
223225
this.packet(packet, flags);
224226

225227
return true;
@@ -710,8 +712,8 @@ export class Socket<
710712
}
711713

712714
/**
713-
* Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
714-
* callback.
715+
* Adds a listener that will be fired when any event is received. The event name is passed as the first argument to
716+
* the callback.
715717
*
716718
* @param listener
717719
* @public
@@ -723,8 +725,8 @@ export class Socket<
723725
}
724726

725727
/**
726-
* Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
727-
* callback. The listener is added to the beginning of the listeners array.
728+
* Adds a listener that will be fired when any event is received. The event name is passed as the first argument to
729+
* the callback. The listener is added to the beginning of the listeners array.
728730
*
729731
* @param listener
730732
* @public
@@ -736,7 +738,7 @@ export class Socket<
736738
}
737739

738740
/**
739-
* Removes the listener that will be fired when any event is emitted.
741+
* Removes the listener that will be fired when any event is received.
740742
*
741743
* @param listener
742744
* @public
@@ -769,6 +771,114 @@ export class Socket<
769771
return this._anyListeners || [];
770772
}
771773

774+
/**
775+
* Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
776+
* callback.
777+
*
778+
* @param listener
779+
*
780+
* <pre><code>
781+
*
782+
* socket.onAnyOutgoing((event, ...args) => {
783+
* console.log(event);
784+
* });
785+
*
786+
* </pre></code>
787+
*
788+
* @public
789+
*/
790+
public onAnyOutgoing(listener: (...args: any[]) => void): this {
791+
this._anyOutgoingListeners = this._anyOutgoingListeners || [];
792+
this._anyOutgoingListeners.push(listener);
793+
return this;
794+
}
795+
796+
/**
797+
* Adds a listener that will be fired when any event is emitted. The event name is passed as the first argument to the
798+
* callback. The listener is added to the beginning of the listeners array.
799+
*
800+
* @param listener
801+
*
802+
* <pre><code>
803+
*
804+
* socket.prependAnyOutgoing((event, ...args) => {
805+
* console.log(event);
806+
* });
807+
*
808+
* </pre></code>
809+
*
810+
* @public
811+
*/
812+
public prependAnyOutgoing(listener: (...args: any[]) => void): this {
813+
this._anyOutgoingListeners = this._anyOutgoingListeners || [];
814+
this._anyOutgoingListeners.unshift(listener);
815+
return this;
816+
}
817+
818+
/**
819+
* Removes the listener that will be fired when any event is emitted.
820+
*
821+
* @param listener
822+
*
823+
* <pre><code>
824+
*
825+
* const handler = (event, ...args) => {
826+
* console.log(event);
827+
* }
828+
*
829+
* socket.onAnyOutgoing(handler);
830+
*
831+
* // then later
832+
* socket.offAnyOutgoing(handler);
833+
*
834+
* </pre></code>
835+
*
836+
* @public
837+
*/
838+
public offAnyOutgoing(listener?: (...args: any[]) => void): this {
839+
if (!this._anyOutgoingListeners) {
840+
return this;
841+
}
842+
if (listener) {
843+
const listeners = this._anyOutgoingListeners;
844+
for (let i = 0; i < listeners.length; i++) {
845+
if (listener === listeners[i]) {
846+
listeners.splice(i, 1);
847+
return this;
848+
}
849+
}
850+
} else {
851+
this._anyOutgoingListeners = [];
852+
}
853+
return this;
854+
}
855+
856+
/**
857+
* Returns an array of listeners that are listening for any event that is specified. This array can be manipulated,
858+
* e.g. to remove listeners.
859+
*
860+
* @public
861+
*/
862+
public listenersAnyOutgoing() {
863+
return this._anyOutgoingListeners || [];
864+
}
865+
866+
/**
867+
* Notify the listeners for each packet sent (emit or broadcast)
868+
*
869+
* @param packet
870+
*
871+
* @private
872+
*/
873+
private notifyOutgoingListeners(packet: Packet) {
874+
if (this._anyOutgoingListeners && this._anyOutgoingListeners.length) {
875+
const listeners = this._anyOutgoingListeners.slice();
876+
for (const listener of listeners) {
877+
listener.apply(this, packet.data);
878+
}
879+
}
880+
}
881+
772882
private newBroadcastOperator(): BroadcastOperator<EmitEvents, SocketData> {
773883
const flags = Object.assign({}, this.flags);
774884
this.flags = {};

‎test/socket.io.ts

+95-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use strict";
22

3-
import { Server, Socket, Namespace } from "..";
3+
import { Server, Socket, Namespace } from "../lib";
44
import { createServer } from "http";
55
import fs = require("fs");
66
import { join } from "path";
@@ -2082,6 +2082,100 @@ describe("socket.io", () => {
20822082
});
20832083
});
20842084
});
2085+
2086+
describe("onAnyOutgoing", () => {
2087+
it("should call listener", (done) => {
2088+
const srv = createServer();
2089+
const sio = new Server(srv);
2090+
2091+
srv.listen(() => {
2092+
const clientSocket = client(srv, { multiplex: false });
2093+
2094+
sio.on("connection", (socket) => {
2095+
socket.onAnyOutgoing((event, arg1) => {
2096+
expect(event).to.be("my-event");
2097+
expect(arg1).to.be("123");
2098+
2099+
success(sio, clientSocket, done);
2100+
});
2101+
2102+
socket.emit("my-event", "123");
2103+
});
2104+
});
2105+
});
2106+
2107+
it("should call listener when broadcasting", (done) => {
2108+
const srv = createServer();
2109+
const sio = new Server(srv);
2110+
2111+
srv.listen(() => {
2112+
const clientSocket = client(srv, { multiplex: false });
2113+
2114+
sio.on("connection", (socket) => {
2115+
socket.onAnyOutgoing((event, arg1) => {
2116+
expect(event).to.be("my-event");
2117+
expect(arg1).to.be("123");
2118+
2119+
success(sio, clientSocket, done);
2120+
});
2121+
2122+
sio.emit("my-event", "123");
2123+
});
2124+
});
2125+
});
2126+
2127+
it("should prepend listener", (done) => {
2128+
const srv = createServer();
2129+
const sio = new Server(srv);
2130+
2131+
srv.listen(async () => {
2132+
const clientSocket = client(srv, { multiplex: false });
2133+
2134+
const socket = (await waitFor(sio, "connection")) as Socket;
2135+
2136+
let count = 0;
2137+
2138+
socket.onAnyOutgoing((event, arg1) => {
2139+
expect(count).to.be(2);
2140+
2141+
success(sio, clientSocket, done);
2142+
});
2143+
2144+
socket.prependAnyOutgoing(() => {
2145+
expect(count++).to.be(1);
2146+
});
2147+
2148+
socket.prependAnyOutgoing(() => {
2149+
expect(count++).to.be(0);
2150+
});
2151+
2152+
socket.emit("my-event", "123");
2153+
});
2154+
});
2155+
2156+
it("should remove listener", (done) => {
2157+
const srv = createServer();
2158+
const sio = new Server(srv);
2159+
2160+
srv.listen(() => {
2161+
const clientSocket = client(srv, { multiplex: false });
2162+
2163+
sio.on("connection", (socket) => {
2164+
const fail = () => done(new Error("fail"));
2165+
2166+
socket.onAnyOutgoing(fail);
2167+
socket.offAnyOutgoing(fail);
2168+
expect(socket.listenersAnyOutgoing.length).to.be(0);
2169+
2170+
socket.onAnyOutgoing(() => {
2171+
success(sio, clientSocket, done);
2172+
});
2173+
2174+
socket.emit("my-event", "123");
2175+
});
2176+
});
2177+
});
2178+
});
20852179
});
20862180

20872181
describe("messaging many", () => {

0 commit comments

Comments
 (0)
Please sign in to comment.