javascripthtmljqueryserver-sent-eventseventsource

Alternative of setInterval for repeating interval only when function get executed


I need any solution or alternative for my Server Sent Event web app. I saw people using setInterval for SSE and which is good, but I have a function that take some time to run completely. Here is a situation that causing my web app to not work perfectly.

Take this example for the root cause. setTimeout will only executed after 1 sec. And setInterval supposed to run that function and then wait for 1/10 sec and then repeat it.

setInterval( () => {
    setTimeout( function () { console.log("ok")}, 1000)
}, 100)

But in just 1 sec setInterval is running that function 10 times.

ok
ok
ok
ok
ok
ok
....
....

This is the actual code. Even if I set some conditions, that function is still running 3 times. And if I set setInterval time to 10 sec then its works fine then.

Is there any alternative in javascript that I can implement for Server Sent Events.

setInterval( () => {
        if ( pu[id] > 0 && pu[id]) {
            connection.query(`SELECT * FROM files WHERE pack_id = ${id} ORDER BY uploaded_at DESC LIMIT ${pu[id]}`, (error, results) => {
                if (error) {
                    console.log(error)
                } else {
                    console.log("SEND") // printing 3 times
                    res.status(200).write(`data: ${JSON.stringify(results)}\n\n`)
                }
                pu[id] = 0
            })
        }
    }, 10)


Solution

  • If I'm understanding correctly, you're having issues with a setInterval time that is shorter than the time it takes your query to resolve?

    If so, you can recursively call a function inside itself with a setTimeout, and that will steady the interval between resolves.

    //query takes 1 second to resolve
    function mockQuery () {
      return new Promise((resolve, reject)=> {
      setTimeout(()=> resolve(console.log("ok")),1000);
    });
    }
    
    async function makeQueryCall(){
      await mockQuery()
      //after resolve it is called again 1/10th of a second later
      setTimeout(()=> makeQueryCall(), 100);
    }
    
    makeQueryCall(); 

    In your code this might translate to

    async function makeQueryCall() {
      if(pu[id] > 0 && pu[id]) {
          try {
              let results = await connection.query(`SELECT * FROM files WHERE pack_id = ${id} ORDER BY uploaded_at DESC LIMIT ${pu[id]}`); 
              console.log("SEND") // printing 3 times
              res.status(200).write(`data: ${JSON.stringify(results)}\n\n`)     
          } catch (e) {
              console.log(e)
          }
          setTimeout(()=> makeQueryCall(),10)
      }
    }
    
    makeQueryCall();
    

    though may require tweaking.