Skip to content
Advertisement

How to programmatically reconnect to server when there is no working connection to the server?

Is there a function/method in socket.io to trigger a ping-pong event from the client-side?

I want to ensure that before the client emits an event that it has a working connection with the server.

For example, when the client goes into standby or sleep mode with the web application open in the background, the socket.io-client still thinks it’s connected. I know this because the socket.connected is still set to true. It’s true until the socket.io ping-pong or heartbeat event (I don’t know what it is called internally) fails.

This is my “maybeReconnect” function that gets called before a socket.emit() call, but it doesn’t work because of the reason above:

const maybeReconnect: () => boolean = () => {
    /**
    * Manually connect to the socket server in case the socket is disconnected
    * this has to be done every time the client tries to emit a socket event
    * but isn't connected to the socket server due to many possible reasons
    * @public
    */
    if (socket && socket.disconnected && !socket.connected) {
        socket.connect();
        return true;
    }
    return false;
};

I don’t want to disconnect every time, like in the code snippet below, because this forced reconnect would happen every time the client emits an event.

socket.disconnect();
socket.connect();

Advertisement

Answer

I buried myself into the socket.io docs and found out there are two built in events “connect” & “disconnect”. With those two events I keep track of the current state of the connection.

Btw. Im using React with TypeScript.

socket.on("connect", () => setState(SocketState.Connected));
socket.on("disconnect", () => setState(SocketState.Disconnected));

On the server side the pingInterval gives the socket.io client the information how often it should pingpong with the server. So setting it to 1000 or 2000 will result in the client realizing in 1 or 2 seconds delay that there is no active connection to the server. Which in my case should be more than enough for the client app to update its UI & hold of any socket.emit() calls until its connected again.

import { Server as SocketServer } from "socket.io";


const io = new SocketServer<ServerToClientEvents, ClientToServerEvents, InterServerEvents, SocketData>(server, {
  pingTimeout:  2000,
  pingInterval: 2000,
  cors: {
    origin: "*",
    methods: ["GET", "POST", "PATCH"],
    credentials: true,
  },
});

The reason I don’t want to call socket.disconnect() with socket.connect() is that my app is fetching data on a custom reconnect I’ve coupled with socket.connect() and calling disconnect & connect every time before a emit would also work as Tim Roberts explained in the comments, but on my app one fetch is the same as 84077 bytes while one ping event is 62 bytes (54 TCP overhead + 8 socket.io). Which means I could pingpong every second for ~23 minutes until I have the size of one fetch.

FIY, there is also the built in “reconnect” event but it fires 3 on every reconnect.

socket.io.on("reconnect", (attempt) => {
  // ...
});
User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement