question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Emitting an event with acknowledgement and timeout breaks the Typescript client-to-server event definitions

See original GitHub issue

Describe the bug Emitting an event using a timeout and acknowledgement causes the acknowledgement function to change its arguments list, so that Error is first argument. This breaks the Typescript definitions. See below for more details:

To Reproduce

Socket.IO client version: 4.5.2

Client

import { io } from "socket.io-client";

interface ClientToServerEvents {
    "withAck": (callback: (data: any) => void) => void;
}
const socket: Socket<ServerToClientEvents, ClientToServerEvents> = io("ws://localhost:3000/", {});

socket.on("connect", () => {
  socket.timeout(5000).emit("withAck", (error, data) => {    // typescript throws here, since the function takes just one parameter as per the ClientToServerEvents interface
        /* If .timeout() is not used, then the first argument is data.
            If .timeout() is used, then first argument is error, second one is data.
            This breaks the ClientToServerEvents interface.
            If you change the ClientToServerEvents interface to have an error argument, 
            then calling the callback from the server breaks, since there data is always first parameter. 
            You need to use different interfaces for client and server.
       */
   });
});

Expected behavior It should be possible to define one ClientToServerEvents interface and use it both with client and server, irrespective if events are emitted with timeout or not.

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
ltomovcommented, Oct 15, 2022

That worked, thanks!

However I notice one small thing:

// server-side
socket.to("some-room").timeout(5000).emit("serverEvent", "some-param", (err, dataParam) => {
    // here dataParam is sent as an array, because there are multiple ACKs - one for each member of the room
});

// client-side
socket.timeout(5000).emit("clientEvent", "some-param", (err, dataParam) => {
    // here dataParam is not an array, because there's only one ACK - the server
});

socket.on("serverEvent", (someParam, callback) => {
    callback("data-param"); // if we define a string here, then the dataParam in the server will be a string, instead of the correct string[]
});

So I modified that helper a bit to introduce a new parameter - isServer - must be true in server-side ServerToClient interface and false in all other cases:

type WithTimeoutAck<isServer extends boolean, isSender extends boolean, args extends any[]> = 
    isSender extends true 
        ? isServer extends true 
            ? [Error, [...args]] 
            : [Error, ...args] 
        : isServer extends true 
            ? [args] 
            : args;
1reaction
darrachequesnecommented, Oct 15, 2022
Read more comments on GitHub >

github_iconTop Results From Across the Web

Emitting events | Socket.IO
IO API is inspired from the Node.js EventEmitter, which means you can emit events on one side and register listeners on the other:....
Read more >
socket.io - Getting an acknowledgment on server send/emit
The socket.io 3.0 document add this timeout example to show how to do that. But the timeout value is the tricky one. const...
Read more >
Event Creation and Handling Techniques in TypeScript
Event emitters act as broadcasters, emitting events at specified points. ... Next, we'll define a start method that begins a timeout.
Read more >
MSFCA Event Health Acknowledgment
Failure to abide by all health and safety protocols implemented for the event is grounds for being asked to leave the event without...
Read more >
How to use Timers and Events in Node.js - Stack Abuse
Clearing session data when a user logs out; Scheduling a timeout for receiving results from an API call and specifying the error handling...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found