【发布时间】:2011-10-04 20:25:27
【问题描述】:
有办法配置javascript的setInterval方法立即执行该方法,然后用定时器执行
【问题讨论】:
-
虽然不是原生的。您可以尝试拨打
function一次,然后拨打setInterval()
有办法配置javascript的setInterval方法立即执行该方法,然后用定时器执行
【问题讨论】:
function 一次,然后拨打setInterval()
第一次直接自己调用函数最简单:
foo();
setInterval(foo, delay);
但是,有充分的理由避免setInterval - 特别是在某些情况下,整个负载的setInterval 事件可以在彼此之后立即到达,没有任何延迟。另一个原因是,如果你想停止循环,你必须显式调用 clearInterval,这意味着你必须记住从原始 setInterval 调用返回的句柄。
因此,另一种方法是让foo 自行触发后续调用,而使用setTimeout:
function foo() {
// do stuff
// ...
// and schedule a repeat
setTimeout(foo, delay);
}
// start the cycle
foo();
这保证了调用之间至少有delay 的间隔。如果需要,它还可以更轻松地取消循环 - 您只是在达到循环终止条件时不要调用 setTimeout。
更好的是,您可以将所有内容包装在一个立即调用的函数表达式中,该表达式创建函数,然后再次调用自身,并自动启动循环:
(function foo() {
...
setTimeout(foo, delay);
})();
定义函数并一次性启动循环。
【讨论】:
setTimeout?
setInterval 事件可以在彼此之后立即到达,没有任何延迟。
setTimeout方法,如何停止该功能?
我不确定我是否理解正确,但您可以轻松地执行以下操作:
setInterval(function hello() {
console.log('world');
return hello;
}(), 5000);
显然有很多方法可以做到这一点,但这是我能想到的最简洁的方法。
【讨论】:
arguments.callee 在 ES5 严格模式下不可用
由于同样的问题,我偶然发现了这个问题,但如果您需要像setInterval() 一样表现得完全,但没有一个答案有帮助,但只有的区别在于函数在开始时立即调用。
这是我对这个问题的解决方案:
function setIntervalImmediately(func, interval) {
func();
return setInterval(func, interval);
}
此方案的优势:
setInterval 的现有代码可以通过替换轻松修改clearInterval()
例子:
// create 1 second interval with immediate execution
var myInterval = setIntervalImmediately( _ => {
console.log('hello');
}, 1000);
// clear interval after 4.5 seconds
setTimeout( _ => {
clearInterval(myInterval);
}, 4500);
老实说,如果你真的需要使用setInterval,那么你也可以替换原来的setInterval。因此,在现有代码之前添加此代码时无需更改代码:
var setIntervalOrig = setInterval;
setInterval = function(func, interval) {
func();
return setIntervalOrig(func, interval);
}
尽管如此,上面列出的所有优点在这里都适用,但不需要替代。
【讨论】:
setTimeout 解决方案,因为它返回一个setInterval 对象。为了避免调用可能在代码中较晚并因此在当前时间未定义的函数,我将第一个函数调用包装在 setTimeout 函数中,如下所示:setTimeout(function(){ func();},0); 然后在当前处理周期之后调用第一个函数,这也是立即,但更多的错误证明。
...args 参数并在每个函数中再次将其用作...args...
您可以将setInterval() 包装在提供该行为的函数中:
function instantGratification( fn, delay ) {
fn();
setInterval( fn, delay );
}
...然后像这样使用它:
instantGratification( function() {
console.log( 'invoked' );
}, 3000);
【讨论】:
如果你需要的话,这里有一个包装器来美化它:
(function() {
var originalSetInterval = window.setInterval;
window.setInterval = function(fn, delay, runImmediately) {
if(runImmediately) fn();
return originalSetInterval(fn, delay);
};
})();
设置setInterval的第三个参数为true,调用setInterval后第一次运行:
setInterval(function() { console.log("hello world"); }, 5000, true);
或者省略第三个参数,它会保持原来的行为:
setInterval(function() { console.log("hello world"); }, 5000);
一些浏览器支持 additional arguments 的 setInterval,这个包装器没有考虑到;我认为这些很少使用,但如果您确实需要它们,请记住这一点。
【讨论】:
这里有一个简单的版本,适合新手,没有任何麻烦。它只是声明函数,调用它,然后开始间隔。就是这样。
//Declare your function here
function My_Function(){
console.log("foo");
}
//Call the function first
My_Function();
//Set the interval
var interval = window.setInterval( My_Function, 500 );
【讨论】:
我会建议按以下顺序调用函数
var _timer = setInterval(foo, delay, params);
foo(params)
如果你想在特定条件下clearInterval(_timer),你也可以将_timer传递给foo
var _timer = setInterval(function() { foo(_timer, params) }, delay);
foo(_timer, params);
【讨论】:
因为有人需要将外部this 带入内部,就好像它是箭头函数一样。
(function f() {
this.emit("...");
setTimeout(f.bind(this), 1000);
}).bind(this)();
如果上述产生垃圾的问题困扰您,您可以改为关闭。
(that => {
(function f() {
that.emit("...");
setTimeout(f, 1000);
})();
})(this);
或者根据您的代码考虑使用the @autobind decorator。
【讨论】:
为了解决这个问题,我在页面加载后第一次运行该函数。
function foo(){ ... }
window.onload = function() {
foo();
};
window.setInterval(function()
{
foo();
}, 5000);
【讨论】:
有一个方便的 npm 包,名为 firstInterval(完全公开,是我的)。
这里的许多示例不包括参数处理,并且在任何大型项目中更改setInterval 的默认行为都是邪恶的。来自文档:
这种模式
setInterval(callback, 1000, p1, p2);
callback(p1, p2);
等同于
firstInterval(callback, 1000, p1, p2);
如果您是浏览器的老派并且不想要依赖项,则可以从the code. 轻松剪切和粘贴
【讨论】:
您可以设置一个非常小的初始延迟时间(例如 100)并在函数内将其设置为您想要的延迟时间:
var delay = 100;
function foo() {
console.log("Change initial delay-time to what you want.");
delay = 12000;
setTimeout(foo, delay);
}
【讨论】:
// YCombinator
function anonymous(fnc) {
return function() {
fnc.apply(fnc, arguments);
return fnc;
}
}
// Invoking the first time:
setInterval(anonymous(function() {
console.log("bar");
})(), 4000);
// Not invoking the first time:
setInterval(anonymous(function() {
console.log("foo");
}), 4000);
// Or simple:
setInterval(function() {
console.log("baz");
}, 4000);
好吧,这太复杂了,所以,让我说得更简单一些:
function hello(status ) {
console.log('world', ++status.count);
return status;
}
setInterval(hello, 5 * 1000, hello({ count: 0 }));
【讨论】:
你的函数的立即异步调用存在问题,因为标准的 setTimeout/setInterval 有一个大约几毫秒的最小超时,即使你直接将它设置为 0。它是由浏览器特定的工作引起的。
一个真正的零延迟代码示例,适用于 Chrome、Safari、Opera
function setZeroTimeout(callback) {
var channel = new MessageChannel();
channel.port1.onmessage = callback;
channel.port2.postMessage('');
}
您可以找到更多信息here
在第一次手动调用之后,您可以使用您的函数创建一个间隔。
【讨论】:
其实最快的就是做
interval = setInterval(myFunction(),45000)
这将调用 myfunction,然后每 45 秒再执行一次,这与执行不同
interval = setInterval(myfunction, 45000)
它不会调用它,但只会安排它
【讨论】:
myFunction() 确实返回自身时有效。而是修改要由 setInterval 调用的每个函数,这是一种更好的方法来包装 setInterval 一次,就像其他答案所建议的那样。