我正在编写一个以可变间隔发送警报的机器人。我正在使用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);
}
}
示例输入是: 输入第一个输入:从现在开始5分钟后每8小时设置一次警报(“呼叫Bob”)
输入第二个输入:从现在开始4分钟后每隔8小时设置一次警报(“调用Jane”)
在4分钟内,我正确地得到“呼叫简”(这个从机器人代码中设置) 一分钟后,我正确地“打电话给Bob”,但我也得到了“打电话给Jane”(直到8小时后才会发生)
我打印了所有超时值,看起来是正确的。我也在issueAlarm()函数中打印setTimeout()函数的返回。
第一次通话中:_idleTimeout:59994(这是正确的,下一次通话是在一分钟内)
在第二个电话中:_idleTimeout:28739994(这看起来很正确,大约8个小时,但我仍然可以立即接到第三个电话)
在第三个调用中:_idleTimeout:28799991(此超时看起来正确,但不应该发生此函数调用)
我正在使用botFramework。我对JavaScript和node.js的了解远非广泛。我已经打印出了我能想到的一切,但我无法弄清楚为什么第三次电话会立刻被制作出来。
仅当输入的第一个输入请求的警报晚于第二个输入中输入的警报时,才会发生这种情况。但我不可能理解为什么。
答案 0 :(得分:2)
我认为你可能会遇到使用Next函数返回数据的问题,看看我的例子。如果您的函数在保存时返回下一个元素,则无法使用该函数,您需要构建一个函数来返回要调用的第一个警报。希望它有所帮助!
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 );
&#13;
<div id="alarms"></div>
&#13;
答案 1 :(得分:0)
(代表OP发布)。
问题出在这里,在机器人代码中:
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分钟,&#39;调用Bob&#39;)从未被清除。
感谢@ guest271314和@damianfabian帮助我找到正确的答案。