Javascript计时:如何每5、7和8秒执行一个函数
Javascript Timing: How do I execute a function every 5, 7, and 8 seconds?
假设我有一个函数log()
var log = function(i) {
console.log('Executing at time: ' + i);
}
我想每隔x、y和z秒执行一次log()
?
让我们任意设置x、y和z为5、7和8。
var x = 5;
var y = 7;
var z = 8;
每x、y和z秒,我都想调用log()
:
// Every 5 seconds:
log(x);
// Every 7 seconds:
log(y);
// Every 8 seconds:
log(z);
我可以尝试使用三个setTimeout()
单独运行这些函数。但是等等,javascript不是异步的,所以一个setTimeout()
的执行将阻止其他两个的执行。。。嗯…
我可以计算时间的差异,这样第一个setTimeout()
引起的延迟就不会破坏第二个和第三个的定时:
// x is at 5 seconds, run 5000 milliseconds after the start
setTimeout(function() { log(x); }, 5000);
// y is at 7 seconds after start, or 2000 milliseconds after x is done
setTimeout(function() { log(y); }, 2000);
// z is at 7 seconds after start, or 1000 milliseconds after y is done
setTimeout(function() { log(z); }, 1000);
但时机永远不会完全正确,因为我的log()
函数的执行至少需要一小段时间。此外,当我尝试在中添加更多log()
命令时,或者当我尝试以设定的间隔重复整个过程时,这会很混乱。
我可以使用循环,计算秒数,在x、y和z秒执行我的命令:
var i = 0;
while(i<10) {
// wait 1 second (pointless function, don't know a better way to wait a second)
setTimeout(function() { console.log(' ... '); }, 1000);
i++;
// execute x, y, or z depending on what time it is
switch(i) {
case 4:
log(x);
case 6:
log(y);
case 7:
log(z);
}
}
但这种"计数"方法,即我使用setTimeout()执行一个无用的命令,真的让我觉得效率低下。
有没有更好的方法来测量javascript中的时间,并让函数在未来的特定时间执行?对我来说,关键是它不仅仅是"每5秒运行一次log()
",因为我理解这一点。让我困惑的是"在x、y和z时间运行log()
"
您可以使用函数"setInterval"。这里有一个例子:
var interval1Id = setInterval(function(){
console.log("logging every 5 seconds");
},5000);
var interval2Id = setInterval(function(){
console.log("logging every 7 seconds");
},7000);
var interval3Id = setInterval(function(){
console.log("logging every 8 seconds");
},8000);
变量"intervalXId"被保存,以防您想要停止任何间隔。
简单的解决方案是设置一个计时器函数,该函数每秒调用一次,并记录经过的秒数;如果计数是5、7或8的倍数,则计时器函数将调用要执行的函数。
借用ZER0的想法,我将建立一个类似于此的递归超时链——
function startTimeoutChain() { //Represents 1 loop cyele
setTimeout(function() {
log(x);
setTimeout(function() {
log(y);
setTimeout(function() {
log(z);
startTimeoutChain(); // Begin next loop
}, 1000);
}, 2000);
}, 5000);
}
只需调用一次&你应该有一些非常健壮的东西。即使时钟漂移,这些值也会相互校准,因为它们本质上是用时间的增量来完成的。
尽管说实话,我很难理解你是想在某个循环的第5、7、8秒调用这些,还是简单地每5、7和8秒调用一次,独立于某个主循环。
您需要在上一个超时内设置下一个超时:
// x is at 5 seconds, run 5000 milliseconds after the start
setTimeout(function() {
log(x);
setTimeout(function() {
log(y);
setTimeout(function() {
log(z);
}, 1000);
}, 2000);
}, 5000);
这样,你就不会提前安排所有的超时,而是一次只安排一次,而且错误幅度较小(第二次超时将在第一次超时结束后开始,以此类推
编辑事实上,我错过了OP希望重复这一点。在这种情况下,您只需要有第一个带有名称而不是匿名名称的函数表达式,并在最后调用它:
setTimeout(function entry() {
log(x);
setTimeout(function() {
log(y);
setTimeout(function() {
log(z);
setTimeout(entry, 5000);
}, 1000);
}, 2000);
}, 5000);
我的评论是要避免嵌套,所以你可以采取类似承诺的方法。请注意,使用jm0这样的附加函数也可以实现这一点,但这会对范围造成额外的污染,使用函数表达式可以避免这种情况。
hmmm一个简单的解决方案可能是这样的。不过,对于jQuery,如果只有这三个间隔,那么一个很好的解决方案就是使用延迟。
function log (val) {
console.log(val);
}
var intervals = [{interval: 5000, logVal: 'x', logged: false},
{interval: 7000, logVal: 'y', logged: false},
{interval: 8000, logVal: 'z', logged: false}];
var startTime;
function myLog () {
var endTime = new Date().getTime();
var diff = endTime - startTime;
for (var i = 0; i < (intervals.length - 1); i++) {
if (diff >= intervals[i].interval && diff < intervals[i+1].interval && !intervals[i].logged) {
log(intervals[i].logVal);
intervals[i].logged = true;
}
}
// for last interval
if (diff >= intervals[i].interval) {
log(intervals[i].logVal);
startTime = new Date().getTime();
return;
}
// Reset Time and run again
setTimeout(myLog, 500);
}
startTime = new Date().getTime();
setTimeout(myLog, 1000);
这是小提琴http://jsfiddle.net/jD8zn/4/
- 如何做到这一点,使代码在不传递条件后执行函数
- javascript自执行函数-不同的语法
- JavaScript:只有当数组中的所有项都为true时才执行函数
- iFrame url更改时执行函数
- 为什么AngularJS在每个摘要循环上都执行函数
- 如何使用setInterval执行函数
- 当*ngFor以角度2结束时执行函数
- Ajax调用完成后如何执行函数
- 在显示引导弹出窗口之前执行函数
- 从自执行函数返回函数的Javascript性能命中率
- 在操作完成时执行函数
- jquery/js中的自执行函数
- 如何仅在完成对gap.client.youtube的请求.execute后执行函数
- 构造函数函数中的自执行函数的OO上下文/范围
- Javascript未使用=运算符执行函数
- AngularJS:如何按照预定义的顺序执行函数
- 在不使用隔离作用域的情况下执行函数的角度指令
- 如何在页面加载后执行函数是在 AngularJS 中完成的
- 完成页面加载后执行函数
- 如何在完成完全执行函数后触发循环