Skip to content

Commit 7ddad2c

Browse files
feat: add volatile events
A volatile packet will be dropped if: - the socket is not connected - the low-level transport is not ready (for example, a HTTP POST request is already pending) Syntax: ```js socket.volatile.emit("volatile event", "might or might not be sent"); ```
1 parent b600e78 commit 7ddad2c

File tree

2 files changed

+73
-3
lines changed

2 files changed

+73
-3
lines changed

lib/socket.ts

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ const RESERVED_EVENTS = {
2828
removeListener: 1,
2929
};
3030

31+
interface Flags {
32+
compress?: boolean;
33+
volatile?: boolean;
34+
}
35+
3136
export class Socket extends Emitter {
3237
public readonly io: Manager;
3338

@@ -42,7 +47,7 @@ export class Socket extends Emitter {
4247
private acks: object = {};
4348
private receiveBuffer: Array<any> = [];
4449
private sendBuffer: Array<any> = [];
45-
private flags: any = {};
50+
private flags: Flags = {};
4651
private subs: Array<any>;
4752

4853
/**
@@ -136,7 +141,7 @@ export class Socket extends Emitter {
136141
};
137142

138143
packet.options = {};
139-
packet.options.compress = !this.flags || false !== this.flags.compress;
144+
packet.options.compress = this.flags.compress !== false;
140145

141146
// event ack callback
142147
if ("function" === typeof args[args.length - 1]) {
@@ -145,7 +150,16 @@ export class Socket extends Emitter {
145150
packet.id = this.ids++;
146151
}
147152

148-
if (this.connected) {
153+
const isTransportWritable =
154+
this.io.engine &&
155+
this.io.engine.transport &&
156+
this.io.engine.transport.writable;
157+
158+
const discardPacket =
159+
this.flags.volatile && (!isTransportWritable || !this.connected);
160+
if (discardPacket) {
161+
debug("discard packet as the transport is not currently writable");
162+
} else if (this.connected) {
149163
this.packet(packet);
150164
} else {
151165
this.sendBuffer.push(packet);
@@ -406,4 +420,16 @@ export class Socket extends Emitter {
406420
this.flags.compress = compress;
407421
return this;
408422
}
423+
424+
/**
425+
* Sets a modifier for a subsequent event emission that the event message will be dropped when this socket is not
426+
* ready to send messages.
427+
*
428+
* @returns {Socket} self
429+
* @public
430+
*/
431+
public get volatile(): Socket {
432+
this.flags.volatile = true;
433+
return this;
434+
}
409435
}

test/socket.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,48 @@ describe("socket", function () {
190190
/"disconnecting" is a reserved event name/
191191
);
192192
});
193+
194+
describe("volatile packets", () => {
195+
it("should discard a volatile packet when the socket is not connected", (done) => {
196+
const socket = io({ forceNew: true, autoConnect: false });
197+
198+
socket.volatile.emit("getId", () => {
199+
done(new Error("should not happen"));
200+
});
201+
202+
socket.emit("getId", () => {
203+
socket.disconnect();
204+
done();
205+
});
206+
207+
socket.connect();
208+
});
209+
210+
it("should discard a volatile packet when the pipe is not ready", (done) => {
211+
const socket = io({ forceNew: true });
212+
213+
socket.on("connect", () => {
214+
socket.emit("getId", () => {
215+
socket.disconnect();
216+
done();
217+
});
218+
219+
socket.volatile.emit("getId", () => {
220+
done(new Error("should not happen"));
221+
});
222+
});
223+
});
224+
225+
it("should send a volatile packet when the socket is connected and the pipe is ready", (done) => {
226+
const socket = io({ forceNew: true });
227+
228+
const interval = setInterval(() => {
229+
socket.volatile.emit("getId", () => {
230+
clearInterval(interval);
231+
socket.disconnect();
232+
done();
233+
});
234+
}, 200);
235+
});
236+
});
193237
});

0 commit comments

Comments
 (0)