setTimeout()函数被连续调用两次
setTimeout() function being called twice in a row
我正在编写一个以可变间隔发送警报的机器人。我正在使用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小时提醒一次("call Bob")
第二个输入:设置从现在开始4分钟每8小时提醒一次("call Jane")
在4分钟内,我正确地得到"call Jane"(这个从bot代码中设置)一分钟后,我正确地得到了"打电话给鲍勃",但我也得到了"打电话给简"(这应该直到8小时后才发生)
我打印了所有的超时值,它们看起来是正确的。我还在issueAlarm()函数中打印setTimeout()函数的返回值。
第一次调用内部:_idleTimeout: 59994(这是正确的,下一个调用将在一分钟内)
在第二个调用中:_idleTimeout: 28739994(这看起来是正确的,它大约是8小时,但我仍然马上得到第三个调用)
在第三个调用中:_idleTimeout: 28799991(这个超时看起来是正确的,但是这个函数调用不应该发生)
我正在使用botFramework。我对JavaScript和node.js的了解还远远不够广泛。我已经把我能想到的都打印出来了,但我不明白为什么第三个电话马上就打了。
只有当第一个输入请求的警报开始时间晚于第二个输入时才会发生这种情况。但我不明白为什么。
我认为您可能对返回数据的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 );
<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分钟,'call Bob')从未被清除。
感谢@guest271314和@damianfabian帮我找到正确答案。
- Meteor Router数据函数被调用两次
- Backbone.js ListenToOnce被调用两次
- 当我的单元测试失败时,回调被调用了两次
- 我的jQuery加载请求是否被调用了两次
- 为什么DTM数据元素被调用两次
- jQuery 方法调用了两次
- 模态中的数据关闭在单击时被调用两次
- 调用一个函数两次
- java-script 函数被调用两次
- 查找与通过两次调用地理编码创建的两个 latlng 对象的距离
- Primefaces:RequestContext.execute-调用了两次Javascript
- 在一个页面中包含两次的脚本中调用函数
- 调用随机函数Javascript,但不能两次调用相同的函数
- 如何防止在快速单击时两次调用en事件处理程序
- 在AngularJS中,一次进行两次调用是一种可接受的方法
- jquery停止两次调用委派事件
- 我没有'我不想两次调用自定义函数
- Javascript:两次调用函数会导致不必要的行为
- 当两次调用一个方法时,仅呈现一个SVG组件
- JavaScript在两次调用之间占用额外时间