第一次没有延迟地执行setInterval函数

Jor*_*rge 296 javascript setinterval

它有一种方法可以配置setIntervaljavascript方法立即执行该方法,然后使用计时器执行

Aln*_*tak 469

第一次直接调用函数是最简单的:

foo();
setInterval(foo, delay);
Run Code Online (Sandbox Code Playgroud)

然而,有充分的理由要避免setInterval- 特别是在某些情况下,整个setInterval事件的负载可以在没有任何延迟的情况下立即到达.另一个原因是,如果你想要停止循环,你必须明确调用clearInterval,这意味着你必须记住从原始setInterval调用返回的句柄.

因此,另一种方法是使用foo触发器本身进行后续调用setTimeout:

function foo() {
   // do stuff
   // ...

   // and schedule a repeat
   setTimeout(foo, delay);
}

// start the cycle
foo();
Run Code Online (Sandbox Code Playgroud)

这保证了呼叫之间至少存在间隔delay.如果需要,它还可以更容易地取消循环 - 只是setTimeout在达到循环终止条件时不会调用.

更好的是,您可以将所有内容包装在一个立即调用的函数表达式中,该表达式创建函数,然后再按上面的方式调用自身,并自动启动循环:

(function foo() {
    ...
    setTimeout(foo, delay);
})();
Run Code Online (Sandbox Code Playgroud)

它定义了函数并一次性启动循环.

  • @Sangdol因为它确保定时器事件如果没有被处理则不会"堆叠".在某些情况下,"setInterval"事件的整个负载可以在没有任何延迟的情况下立即到达. (17认同)
  • @JamesAndino,因为它使用`setTimeout`和**而不是**`setInterval` ... (9认同)
  • 应该有某种测试,当你累了的时候不会让你在堆叠上发布 (7认同)
  • 为什么你更喜欢`setTimeout`? (5认同)
  • @DaveMunger不,因为它不是真正的递归 - 它只是"伪递归".在浏览器返回事件循环之前,"递归"调用不会发生,此时调用堆栈已完全展开. (5认同)
  • 如果我使用`setTimeout`方法,如何停止该函数? (3认同)
  • 我喜欢你发布的最后一段代码。setTimeout() 的优点是;您保证上一个周期在第二个周期安排之前就完成了。 (2认同)
  • @GauravBhor,与停止 setInterval 的方式相同,记住 setTimeout 返回的 id,然后调用 clearTimeout(id)... 或者设置条件以在函数中的下一个间隔运行或不运行。 (2认同)

chj*_*hjj 190

我不确定我是否正确理解你,但你可以很容易地做到这样的事情:

setInterval(function hello() {
  console.log('world');
  return hello;
}(), 5000);
Run Code Online (Sandbox Code Playgroud)

显然有很多方法可以做到这一点,但这是我能想到的最简洁的方式.

  • 绝对是一个很酷的解决方案,但可能会给将来读书的人造成混乱. (36认同)
  • 这是一个很酷的答案,因为它是一个命名函数,可以立即执行并返回自身.正是我在寻找什么. (16认同)
  • @JochenJung` arguments.callee`在ES5严格模式下不可用 (10认同)
  • 不要使用这个。在将其作为参数传递之前很难看出它被调用。作为 JS 开发人员,我喜欢它(我不知道),但我更喜欢干净的代码。 (5认同)
  • 你不需要给它起个名字'hello'.你可以改为使用匿名函数返回arguments.callee并使用相同的函数 (4认同)
  • 这种Javascript代码会使大多数来自其他语言的新JS程序员感到困惑。如果您的公司没有很多JS人员并且您想要工作安全,请编写这样的一堆东西。 (3认同)
  • 任何像这样的代码最好有注释来表明它打算做什么,否则修改它或修复错误的人可能会遇到问题。旁注:当然,现在我看到人们不会在他们的代码中添加注释,因为公司希望让程序员变得可有可无,(一些)程序员希望让自己尽可能不可或缺,或者在公司中获得权力。但是然后这个程序员可能会离开,而且不同程序员的很多代码没有这样的注释,整个代码库就会变得一团糟 (2认同)

Jen*_*rth 12

由于同样的问题,我偶然发现了这个问题,但是如果你需要表现得非常相似,但没有任何答案会有所帮助,setInterval()唯一的区别就是在开始时立即调用该函数.

以下是我对此问题的解决方案:

function setIntervalImmediately(func, interval) {
  func();
  return setInterval(func, interval);
}
Run Code Online (Sandbox Code Playgroud)

这个解决方案的优点:

  • 使用的现有代码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);
Run Code Online (Sandbox Code Playgroud)

要厚颜无耻,如果你真的需要使用setInterval那么你也可以替换原来的setInterval.因此,在现有代码之前添加此代码时,不需要更改代码:

var setIntervalOrig = setInterval;

setInterval = function(func, interval) {
    func();
    return setIntervalOrig(func, interval);
}
Run Code Online (Sandbox Code Playgroud)

尽管如此,上面列出的所有优点都适用于此,但不需要替换.


use*_*716 7

您可以包装setInterval()一个提供该行为的函数:

function instantGratification( fn, delay ) {
    fn();
    setInterval( fn, delay );
}
Run Code Online (Sandbox Code Playgroud)

...然后像这样使用它:

instantGratification( function() {
    console.log( 'invoked' );
}, 3000);
Run Code Online (Sandbox Code Playgroud)

  • 我想你应该返回setInterval返回的内容.这是因为否则你不能使用clearInterval. (4认同)

Mah*_*ahn 6

如果你需要的话,这里有一个非常好的包装:

(function() {
    var originalSetInterval = window.setInterval;

    window.setInterval = function(fn, delay, runImmediately) {
        if(runImmediately) fn();
        return originalSetInterval(fn, delay);
    };
})();
Run Code Online (Sandbox Code Playgroud)

将setInterval的第三个参数设置为true,它将在调用setInterval后立即第一次运行:

setInterval(function() { console.log("hello world"); }, 5000, true);
Run Code Online (Sandbox Code Playgroud)

或者省略第三个参数,它将保留其原始行为:

setInterval(function() { console.log("hello world"); }, 5000);
Run Code Online (Sandbox Code Playgroud)

有些浏览器支持setInterval的其他参数,而这个参数不考虑这个包装器; 我认为这些很少使用,但如果你确实需要它们,请记住这一点.

  • 覆盖本机浏览器功能非常糟糕,因为它可以在规范更改时破坏其他共存代码.实际上,setInterval目前有更多参数:https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setInterval (8认同)

Pol*_*cks 5

这是一个适合新手的简单版本,无需任何混乱。它只是声明函数,调用它,然后开始间隔。就是这样。

//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 );
Run Code Online (Sandbox Code Playgroud)

  • 这正是已接受的答案在前几行中所做的。这个答案如何添加新内容? (2认同)