setTimeout()函数连续调用两次

我正在写一个bot,以可变间隔发送警报。 我正在使用setTimeout(),我有一个问题,我似乎无法弄清楚。 (简化)代码是:

//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); } } 

示例input如下:input的第一个input:从现在起的5分钟开始每8小时设置一次警报(“call Bob”)

input第二个input:从现在开始4分钟,每8小时设置一次警报(“致电简”)

在4分钟内,我正确地得到了“致电简”(这个从机器人代码中获得)。一分钟后,我正确地打电话给鲍勃,但是我也打电话给了简(直到8小时后才发生) )

我打印所有的超时值,他们似乎是正确的。 我还打印issueAlarm()函数内的setTimeout()函数的返回值。

在第一个电话内部:_idleTimeout:59994(这是正确的,下一个电话在一分钟内)

在第二个电话内部:_idleTimeout:28739994(这看起来正确,大概是8个小时,但我仍然可以立刻得到第三个电话)

在第三个调用中:_idleTimeout:28799991(这个超时看起来是正确的,但是这个函数调用不应该发生)

我正在使用botFramework。 我对JavaScript和node.js的知识远非广泛。 我印出了所有我能想到的东西,但我无法弄清楚为什么第三个电话正在被立即执行。

只有当input的第一个input请求一个比在第二个input中input的更晚开始的警报时,才会发生这种情况。 但我不明白为什么。

我以为你可能有一个问题,下一个函数返回你的数据,看看我的例子。 如果您的函数在保存时返回下一个元素,则无法使用该函数,您需要构build一个返回第一个要调用的警报的函数。 希望能帮助到你!

 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> 

(代表OP发布)

问题在这里,在bot代码中:

 if (nextD.timestamp >= mom.valueOf() ){ var now = new Date(); clearTimeout(timeout); timeout = mom.valueOf() - now; setTimeout(issueAlarm, timeout); } 

我第一次正确清除超时(当我清除2 ^ 31 – 1的原始超时),但不是之后。 问题是我调用setTimeout的行应该是

 timeout = setTimeout(issueAlarm, timeout); 

这样返回就存储在一个超时对象中。 我正在通过传递一个值而不是一个对象来调用clearTimeout(),因此第一个存储的超时值(5分钟,“调用Bob”)从未被清除。

感谢@ guest271314和@damianfabian帮助我得到正确的答案。