diff --git a/packages/socket.io-client/lib/socket.ts b/packages/socket.io-client/lib/socket.ts index cc8ff87df..0d57a6192 100644 --- a/packages/socket.io-client/lib/socket.ts +++ b/packages/socket.io-client/lib/socket.ts @@ -544,7 +544,7 @@ export class Socket< flags: Object.assign({ fromQueue: true }, this.flags), }; - args.push((err, ...responseArgs) => { + const onResponse = (err, ...responseArgs) => { if (packet !== this._queue[0]) { return debug("packet [%d] already acknowledged", packet.id); } @@ -570,7 +570,10 @@ export class Socket< } packet.pending = false; return this._drainQueue(); - }); + }; + // the first argument is always the error (or null), even without the "ackTimeout" option + onResponse.withError = true; + args.push(onResponse); this._queue.push(packet); this._drainQueue(); diff --git a/packages/socket.io-client/test/retry.ts b/packages/socket.io-client/test/retry.ts index 9ceca208b..13368877e 100644 --- a/packages/socket.io-client/test/retry.ts +++ b/packages/socket.io-client/test/retry.ts @@ -111,6 +111,41 @@ describe("retry", () => { }); }); + it("should not treat the acknowledgement as an error without ackTimeout", () => { + return wrap((done) => { + const socket = io(BASE_URL, { + forceNew: true, + retries: 3, + }); + + const sent: string[] = []; + + socket.io.engine.on("packetCreate", ({ data }) => { + sent.push(data); + }); + + socket.emit("echo", 1, (err, val) => { + expect(err).to.be(null); + expect(val).to.eql(1); + expect(sent).to.eql(["0", '20["echo",1]']); + + success(done, socket); + }); + }); + }); + + it("should resolve emitWithAck() without ackTimeout", async () => { + const socket = io(BASE_URL, { + forceNew: true, + retries: 3, + }); + + const val = await socket.emitWithAck("echo", 2); + expect(val).to.eql(2); + + socket.disconnect(); + }); + it("should not emit a packet twice in the 'connect' handler", () => { return wrap((done) => { const socket = io(BASE_URL, {