Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setTimeout() function being called twice in a row

I am writing a bot that sends alerts at variable intervals. I am using setTimeout() and I have an issue I can't seem to be able to figure out. The (simplified) code is:

//Original call to setTimeout():

timeout = setTimeout(issueAlarm, 2147483647); // highest possible interval setTimeout() will accept. 

//In bot:
// dh is a priority queue that keeps timestamps sorted from smaller to larger as the user requests alerts. 
//'mom' is a moment.js variable that holds the most recent request. 
//This block of code checks the PQ and if what the user just entered is smaller than what is already stored, it updates the timeout. 
//This seems to work fine
// First get input from user and store the desired time of first alert in 'mom'. Then:
var nextD = dh.peekNext();
if (nextD.timestamp >= mom.valueOf() ){
    var now = new Date();        
    clearTimeout(timeout);
    timeout = mom.valueOf() - now;
    setTimeout(issueAlarm, timeout);
    }

//issueAlarm function:

function issueAlarm() {
    var next = dh.getNext(); // this pops the first alarm from the queue
    // here goes some code that issues message. Then:
    var peek = dh.peekNext(); // this looks at the next element in the queue without popping it
    if (peek) {
        var now = new Date();
        timeout = peek.timestamp - now;
        setTimeout(issueAlarm, timeout);
        }
    }

The example inputs are: First input entered: Set an alert every 8 hours starting 5 minutes from now ("call Bob")

Second input entered: Set an alert every 8 hours starting 4 minutes from now ("call Jane")

In 4 minutes, i correctly get "call Jane" (this one gets set from the bot code) One minute later, I correctly get "call Bob", but also i get "call Jane" (which should not happen until 8 hours later)

I printed all the timeout values and they seem correct. I also am printing the return of the setTimeout() function inside the issueAlarm() function.

Inside the first call: _idleTimeout: 59994 (this is correct, the next call is in one minute)

Inside the second call: _idleTimeout: 28739994 (this looks correct, it's approximately 8 hours, but still i get a third call right away)

Inside the third call: _idleTimeout: 28799991 (this timeout looks correct but this function call shouldn't have happened)

I'm using botFramework. My knowledge of JavaScript and node.js is far from extensive. I have printed out everything I could think of, but I can't figure out why that third call is being made right away.

This happens only if the first input entered requests an alert that starts later than the one entered in the second input. But I can't possibly understand why.

like image 894
Irene Avatar asked Oct 29 '22 19:10

Irene


1 Answers

I thought you could have a problem with the Next function that returns you the data, take a look to my example. If your function is returning the next element as they were saved, you could not use that function, you need to build a function that return the first alarm to call. Hope it helps!

var dh = {};
dh.alarms = [{time: 1000, name:"Jane"},{time:5000, name:"Jane"},{time: 3000, name:"Bob"}];

dh.first = function(){
dh.alarms = dh.alarms.sort(function(a,b){return a.time - b.time});
next = dh.alarms.slice(0,1);
dh.alarms = dh.alarms.slice(1);
return next[0]
}

dh.next = function(){
next = dh.alarms.slice(0,1);
dh.alarms = dh.alarms.slice(1);
return next[0]
}

var timeout = setTimeout(executeAlarm, 2999999);

function start(){
    
  var next = dh.first(); // dh.next(); I thought this is your problem!!
  if(next && next.name){

    clearInterval(timeout);
    timeout = setTimeout(function(){executeAlarm(next)},next.time);
  }
  
}

function executeAlarm(next){
  if(!next || !next.name) clearInterval(timeout)
  document.getElementById("alarms").innerHTML += "<span> Alarm for " + next.name + "</span>";
  start();
}

document.addEventListener( "DOMContentLoaded", start, false );
<div id="alarms"></div>
like image 72
damianfabian Avatar answered Nov 11 '22 04:11

damianfabian