nodejs中的setInterval奇怪行为 [英] setInterval weird behavior in nodejs

查看:32
本文介绍了nodejs中的setInterval奇怪行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想每秒运行一次函数,函数本身需要 3 秒才能执行.结果是每个间隔在<函数执行时间>*2+

我编写了以下示例代码:

var seconds = 3;设置间隔(功能(){console.info(new Date().toString());var waitTill = new Date(new Date().getTime() + seconds * 1000);while(waitTill > new Date()){}},1000);

并且每次迭代都如我在公式中所述:

2016 年 7 月 13 日星期三 09:49:07 GMT+0300 (IDT)2016 年 7 月 13 日星期三 09:49:14 GMT+0300 (IDT)2016 年 7 月 13 日星期三 09:49:21 GMT+0300 (IDT)2016 年 7 月 13 日星期三 09:49:28 GMT+0300 (IDT)

文档没有说明这种行为.我认为的结果是,无论间隔函数的执行需要多少时间,每次迭代都会在 1 秒后执行.

怎么回事?

任何有关该问题的信息将不胜感激.

谢谢!

使用 Nodejs 6.3.0

更新

在浏览器上试过这段代码...谷歌浏览器...这里间隔每3秒执行一次,这仍然很奇怪.

更新

感谢您的所有评论,最后一件事还不清楚.为什么在 NodeJS 中,当我将 setInterval() 设置为 1 秒,并且函数执行需要 3 秒时,为什么下一次执行是 7 秒而不是 4 秒甚至 3 秒.这对我来说似乎很奇怪.这是可以接受的行为吗?

解决方案

文档没有说明这种行为

NodeJS 的 setInterval 文档几乎没有任何关于它的行为,除此之外它会重复任务.

<块引用>

我认为的结果是,无论间隔函数的执行需要多少时间,每次迭代都会在1秒后执行

如果你的意思是你可以有重叠的执行,你不能在 NodeJS 中;它在单个线程上运行您的代码.

如果您的意思是希望每次迭代在最后一次完成后运行一秒钟,那么 setInterval 传统上不是这样工作的.setInterval 传统上至少有两种不同的行为,具体取决于您使用的实现:在当前迭代的开始调度下一次迭代,或在 调度它>end 当前的.这只是在浏览器上.这是因为 已为浏览器标准化,但 NodeJS 不是t 浏览器,不需要以相同的方式工作.(事实上​​,它也不是以另一种方式:在浏览器上,setInterval 需要返回一个数字;在 NodeJS 上,它返回一个对象.)请记住,计时器不是JavaScript,它们是宿主环境的一个特性.

相反,要让它在之前完成后一秒(大约)再次运行,请在函数末尾使用 setTimeout 安排下一秒运行.

重新

<块引用>

为什么在 NodeJS 中,当我将 setInterval() 设置为 1 秒,并且函数执行需要 3 秒时,为什么下一次执行是 7 秒而不是 4 秒甚至 3 秒.这对我来说似乎很奇怪.这是可以接受的行为吗?

是的.这很奇怪和令人惊讶(在我看来),但是 NodeJS 为 setInterval 确定了自己的行为,所以它可以接受.在我的实验中(如下),它似乎测量了您的函数的前一次执行所花费的时间,然后将其添加到计时器长度中,使其在它之前是 lastExecutionLength + desiredInterval再次开火.这与浏览器的规范明显不同,但同样,NodeJS 不是浏览器.

这是我的测试脚本:

let counter = 0;让 timeAtEndOfLastExecution = 0;让计时器=空;功能日志(味精){console.log(Date.now() + ": " + msg);}功能滴答(){让开始 = Date.now();如果(timeAtEndOfLastExecution){log("tick (" + (Date.now() - timeAtEndOfLastExecution) + "ms)");} 别的 {日志(滴答");}如果(++计数器== 10){清除间隔(定时器);} 别的 {让等待 = 200 + (Math.floor(8 * Math.random()) * 100);日志(等待"+等待+毫秒");让 stopWaiting = Date.now() + 等待;而 (Date.now() < stopWaiting) {//忙等待}log("退出回调" + (Date.now() - start) + "ms");timeAtEndOfLastExecution = Date.now();}}timer = setInterval(tick, 200);

以及一个示例运行(使用 Node v6.2.2):

<前>1468396730618:打勾1468396730619:等待400ms1468396731020:416ms 后退出回调1468396731637:滴答(617ms)1468396731637:等待500ms1468396732137:500 毫秒后退出回调1468396732837:滴答(700 毫秒)1468396732837:等待900ms1468396733737:900 毫秒后退出回调1468396734837:滴答(1100毫秒)1468396734837:等待300ms1468396735137:300 毫秒后退出回调1468396735637:滴答(500毫秒)1468396735637:等待700ms1468396736337:700 毫秒后退出回调1468396737237:滴答(900 毫秒)1468396737237:等待800ms1468396738037:800 毫秒后退出回调1468396739036:滴答(999ms)1468396739036:等待900ms1468396739936:900 毫秒后退出回调1468396741036:滴答(1100毫秒)1468396741036:等待700ms1468396741736:700 毫秒后退出回调1468396742636:滴答(900 毫秒)1468396742636:等待200ms1468396742836:200 毫秒后退出回调1468396743236:滴答(400毫秒)

正如我们所见,它一直在等待前一次迭代的长度加上我给出的间隔:

  • 第一次回调总共耗时 416 毫秒;下一个在返回后 617 毫秒开始
  • 第二次回调耗时 500 毫秒;下一个在返回后 700 毫秒开始
  • 第三次回调900ms;下一个在返回后 1100 毫秒开始

I want to run a function once every second, and the function itself takes 3 seconds to execute. the results are that each interval is executed at a difference of <function execution time>*2+<setInterval delay>

I wrote the following sample code:

var seconds = 3;

setInterval(
    function(){
            console.info(new Date().toString());
            var waitTill = new Date(new Date().getTime() + seconds * 1000);
            while(waitTill > new Date()){}
    },1000
);

and each iteration is as I stated in the formula:

Wed Jul 13 2016 09:49:07 GMT+0300 (IDT)
Wed Jul 13 2016 09:49:14 GMT+0300 (IDT)
Wed Jul 13 2016 09:49:21 GMT+0300 (IDT)
Wed Jul 13 2016 09:49:28 GMT+0300 (IDT)

the documentation doesn't state this behaviour. the results that I thought that will be is that each iteration will execute after 1 second no matter how much time the execution of the interval function takes.

what's going on?

any information regarding the issue would be greatly appreciated.

thanks!

using Nodejs 6.3.0

update

tried this code on the browser... google chrome... here the interval executes every 3 seconds, which is still weird.

update

thanks for all of your comments, one last thing that's not clear. why in NodeJS, when I have setInterval() set to 1 second, and the function execution takes 3 seconds, why the next execution is 7 seconds instead of 4 seconds or even 3 seconds. that seems really strange behaviour for me. is that an acceptable behaviour ?

解决方案

the documentation doesn't state this behavior

NodeJS's documentation for setInterval characteristically states virtually nothing about its behavior, other than that it will repeat the task.

the results that I thought that will be is that each iteration will execute after 1 second no matter how much time the execution of the interval function takes

If you mean you could have overlapping executions, you can't in NodeJS; it runs your code on a single thread.

If you mean you expected each iteration to run a second after the last completed, that's not how setInterval traditionally works. setInterval has traditionally had at least two different behaviors depending on which implementation you were using: Scheduling the next iteration at the beginning of the current one, or scheduling it at the end of the current one. And that's just on browsers. It's since been standardized for browsers, but NodeJS isn't a browser and isn't required to work the same way. (And in fact, it doesn't in another way as well: On browsers, setInterval is required to return a number; on NodeJS, it returns an object.) Remember that timers are not a feature of JavaScript, they're a feature of the host environment.

Instead, to get it to run again a second (roughly) after it finished previously, use setTimeout at the end of the function to schedule the next one to run a second later.

Re your edit:

why in NodeJS, when I have setInterval() set to 1 second, and the function execution takes 3 seconds, why the next execution is 7 seconds instead of 4 seconds or even 3 seconds. that seems really strange behavior for me. is that an acceptable behavior ?

Yes. It's strange and surprising (in my view), but NodeJS determines its own behavior for setInterval, so it's acceptable. In my experiments (below), it appears to measure how long the previous execution of your function took, then add that to the timer length so that it's lastExecutionLength + desiredInterval before it fires it again. That's markedly at variance with the spec for browsers, but again, NodeJS isn't a browser.

Here's my test script:

let counter = 0;
let timeAtEndOfLastExecution = 0;
let timer = null;

function log(msg) {
    console.log(Date.now() + ": " + msg);
}

function tick() {
    let start = Date.now();
    if (timeAtEndOfLastExecution) {
        log("tick (" + (Date.now() - timeAtEndOfLastExecution) + "ms)");
    } else {
        log("tick");
    }
    if (++counter == 10) {
        clearInterval(timer);
    } else {
        let wait = 200 + (Math.floor(8 * Math.random()) * 100);
        log("waiting " + wait + "ms");
        let stopWaiting = Date.now() + wait;
        while (Date.now() < stopWaiting) {
            // busy wait
        }
        log("exiting callback after " + (Date.now() - start) + "ms");
        timeAtEndOfLastExecution = Date.now();
    }
}
timer = setInterval(tick, 200);

And a sample run (with Node v6.2.2):

1468396730618: tick
1468396730619: waiting 400ms
1468396731020: exiting callback after 416ms
1468396731637: tick (617ms)
1468396731637: waiting 500ms
1468396732137: exiting callback after 500ms
1468396732837: tick (700ms)
1468396732837: waiting 900ms
1468396733737: exiting callback after 900ms
1468396734837: tick (1100ms)
1468396734837: waiting 300ms
1468396735137: exiting callback after 300ms
1468396735637: tick (500ms)
1468396735637: waiting 700ms
1468396736337: exiting callback after 700ms
1468396737237: tick (900ms)
1468396737237: waiting 800ms
1468396738037: exiting callback after 800ms
1468396739036: tick (999ms)
1468396739036: waiting 900ms
1468396739936: exiting callback after 900ms
1468396741036: tick (1100ms)
1468396741036: waiting 700ms
1468396741736: exiting callback after 700ms
1468396742636: tick (900ms)
1468396742636: waiting 200ms
1468396742836: exiting callback after 200ms
1468396743236: tick (400ms)

As we can see, it's consistently waiting the length of the previous iteration plus the interval I gave:

  • First callback took a total of 416ms; the next started 617ms after it returned
  • Second callback took 500ms; the next started 700ms after it returned
  • Third callback 900ms; the next started 1100ms after it returned

这篇关于nodejs中的setInterval奇怪行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆