javascriptnode.jswebsocketio-socket

How to break setinterval in io sockets - Nodejs


There is an api which sends some json data.The nodejs server get this json data and send client with websocket every 5 seconds.If the connection is on when a clent connects it works but when the client disconnects ,it doesnt stop.

The code

io.on('connection', function(client) {  
        var loop=setInterval(()=>{
            console.log('Client connected...');

            fetch('https://www.foo.com/api/v2/searchAssets')
            .then(res => res.json())
            .then(json => 
            {client.emit('news'{json});console.log(json)}),5000);

        })});

io.on('disconnetion',function(){
                clearInterval(loop);
                console.log("disconnected");
            })

OR

Do you have any other advice to send this json data to client side except websocket?

Thansk in advance for your supporting


Solution

  • Your problem is a scope problem. When you declare the loop var, it's local to the callback of the on connection event and doesn't exist in the on disconnect event. Based on the doc of how to handle disconnection you can move the disconnection handler inside the connection handler like this:

    io.on('connection', function(client) {
      // Start the interval
      var loop = setInterval(()=>{
        console.log('Client connected...');
    
        fetch('https://www.foo.com/api/v2/searchAssets')
          .then(res => res.json())
          .then(json => {
            client.emit('news'{json});console.log(json)
          } ,5000);
      });
    
      // Handles disconnection inside the on connection event
      // Note this is using `client.on`, not `io.on`, and that
      // your original code was missing the "c" in "disconnect"
      client.on('disconnect', () => {
        clearInterval(loop);
        console.log("disconnected");
      });
    });
    

    But I would not recommend this architecture as the streamed data is independent of a client. The data can be fetched once and streamed to all. Here is how you can do it:

    var loop
    
    // The function startStreaming starts streaming data to all the users
    function startStreaming() {
      loop = setInterval(() => {
        fetch('https://www.foo.com/api/v2/searchAssets')
          .then(res => res.json())
          .then(json => {
            // The emit function of io is used to broadcast a message to
            // all the connected users
            io.emit('news', {json});
            console.log(json);
          } ,5000);
      });
    }
    
    // The function stopStreaming stops streaming data to all the users
    function stopStreaming() {
      clearInterval(loop);
    }
    
    io.on('connection',function() {
      console.log("Client connected");
    
      // On connection we check if this is the first client to connect
      // If it is, the interval is started
      if (io.sockets.clients().length === 1) {
        startStreaming();
      }
    });
    
    io.on('disconnetion',function() {
      console.log("disconnected");
    
      // On disconnection we check the number of connected users
      // If there is none, the interval is stopped
      if (io.sockets.clients().length === 0) {
        stopStreaming();
      }
    });