Javascript 加速 setInterval

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5298999/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 16:32:50  来源:igfitidea点击:

Speed up setInterval

javascript

提问by trnc

I know there's a minimum of 1 millisecond in the setInterval method in javascript. Can I speed this up even more? Like using microseconds?

我知道 javascript 的 setInterval 方法中至少有 1 毫秒。我可以加快速度吗?喜欢使用微秒?

for what i need this:

我需要这个:

i make a canvas css/js animation. it's a simple line, which bends into a cure and back to a line. i have a slider to adjust the speed of this animation. so the lowest slider value would be really fast and the highest really slow. is that understandable? thanks!

我制作了一个画布 css/js 动画。这是一条简单的线,它弯曲成治愈并回到一条线。我有一个滑块来调整这个动画的速度。所以最低的滑块值会很快,最高的会很慢。这可以理解吗?谢谢!

回答by rsp

Update:

更新:

Please note that when this answer was written, the question was:

请注意,在撰写此答案时,问题是:

I know there's a minimum of 1 millisecond in the setInterval method in javascript. Can I speed this up even more? Like using microseconds?

我知道 javascript 的 setInterval 方法中至少有 1 毫秒。我可以加快速度吗?喜欢使用微秒?

Later it was edited to include the information about canvas animation and with that new information the correct answer would be using the window.requestAnimationFramemethod:

后来它被编辑以包含有关画布动画的信息,有了这些新信息,正确的答案将是使用该 window.requestAnimationFrame方法:

function step(timestamp) {
  // do something for every frame
  window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);

The stepcallback gets a DOMHighResTimeStamptimestamp with a precision of 1 microsecond as an argument every time it gets invoked, which is once every time the screen gets refreshed (there's no need to draw anything more frequently because it wouldn't get displayed anyway).

step回调得到一个DOMHighResTimeStamp与每次被调用时1微秒精度的参数,它是一次画面被刷新的时间(有没有需要更频繁地画任何东西,因为它不会得到反正显示)日期和时间。

Originally the question was specifically about speeding up the setIntervalmethod, and my original answer was about doing anything in general more frequently than the minimum delayof setIntervalallows (which is 4ms for the nesting levels greater than 5 according to the the WHATWG specification, section 8.4 Timers, or 4ms for the nesting levels of 4 or higher according to this post by James Robinson, and historically it used to work differently).

最初的问题是专门关于加快setInterval方法,和我原来的答复是关于更频繁地做一般什么比最小延迟setInterval允许(这是根据对嵌套层数大于5 4ms的WHATWG的规范,部分8.4定时器,或者根据James Robinson 的这篇文章,对于 4 或更高的嵌套级别为 4 毫秒,并且在历史上它曾经以不同的方式工作)。

Original answer:

原答案:

I don't really know what are you trying to do so I can only speak from experience of what people usually want to do with it.

我真的不知道你想做什么,所以我只能从人们通常想用它做什么的经验中说出来。

If you want to call setInterval using microseconds, then the code you want to run has to take considerably less then a millisecond, or otherwise it wouldn't make sense in a single-threaded event loop.

如果您想使用微秒调用 setInterval ,那么您要运行的代码必须少于一毫秒,否则在单线程事件循环中将没有意义。

You don't have to worry about blocking the browser for a few milcroseconds so I would suggest using something like this – instead of having:

您不必担心会阻止浏览器几微秒,因此我建议使用类似的东西 - 而不是:

setInterval(function () {
    // YOUR CODE
}, 1/100);

Try doing:

尝试做:

setInterval(function () {
    for (var i = 0; i < 1000; i++) {
        // YOUR CODE
    }
}, 10);

You will actually make your code more efficient by avoiding the callback calling overhead and having longer intervals will make your code run more predictably.

通过避免回调调用开销,您实际上将使您的代码更高效,并且更长的间隔将使您的代码运行更可预测。

Also no one is going to notice that your code runs in bursts 1000 times every 1/100 of a second, because there's a chance that the browser itself already runs in such bursts thanks to the OS-level process scheduling, and also the screen won't get refreshed faster anyway.

也没有人会注意到您的代码每 1/100 秒以突发方式运行 1000 次,因为由于操作系统级进程调度,浏览器本身有可能已经以这种突发方式运行,并且屏幕也赢了无论如何都不能更快地刷新。

An experiment

一个实验

Ok, now some experiment. Try this code to see what is actually the shortest interval for your browser:

好的,现在进行一些实验。试试这个代码,看看你的浏览器实际上最短的间隔是多少:

var start = new Date();
var i = 0, interval = setInterval(function(){
    if (++i >= 1000) {
        var end = new Date();
        alert("The average interval was "
              + ((end-start)/1000)) + " milliseconds";
        clearInterval(interval);
    }
}, 0);

Note that it won't even be consistent on the same browser. It depends on your system load for example.

请注意,它甚至不会在同一浏览器上保持一致。例如,这取决于您的系统负载。

Test your browser

测试您的浏览器

Try THIS FIDDLEto test your browser and post your result in the comments if you like. I wonder what will be the record.

试试这个 FIDDLE来测试你的浏览器,如果你愿意,可以在评论中发布你的结果。我想知道记录是什么。

回答by Piotr Salaciak

Note that some browsers won't accept intervals smaller even than 50 milliseconds. If You pass a smaller interval, they will use the smallest they are able to use.

请注意,某些浏览器甚至不接受小于 50 毫秒的间隔。如果您传递较小的间隔,他们将使用他们能够使用的最小间隔。

回答by idbentley

The minimum time is different depending on the browser. A good explanation is here: http://www.adequatelygood.com/2010/2/Minimum-Timer-Intervals-in-JavaScript

最短时间因浏览器而异。一个很好的解释在这里:http: //www.adequatelygood.com/2010/2/Minimum-Timer-Intervals-in-JavaScript

回答by Grant Galitz

FYI, it's gonna be useless to do it less than a few milliseconds between each interval, because canvas ops take a few milliseconds to do their own thing, while blocking your main loop at the same time (single threaded). Doing 1/100 for milliseconds actually gets rounded up to 16 in classical browsers, and 5 milliseconds in chrome.

仅供参考,在每个间隔之间执行少于几毫秒的操作是没有用的,因为画布操作需要几毫秒来做自己的事情,同时阻塞您的主循环(单线程)。以毫秒为单位执行 1/100 实际上在经典浏览器中四舍五入为 16,在 chrome 中为 5 毫秒。

You're doing it wrong if you're trying to time your animation in javascript to microseconds, because that's a futile goal. garbage collection, busy loop timing variance will hurt you, not to mention if you draw too fast you might get frame tearing.

如果您试图将 javascript 中的动画时间设置为微秒,那么您就做错了,因为这是一个徒劳的目标。垃圾收集,忙循环时间差异会伤害你,更不用说如果你画得太快你可能会撕裂帧。

SOLUTION: use requestAnimationFrame to get the maximum FPS out of a browser, and don't forget to provide a fallback to setInterval(..., 16).

解决方案:使用 requestAnimationFrame 从浏览器中获得最大 FPS,并且不要忘记提供对 setInterval(..., 16) 的回退。

https://developer.mozilla.org/en/DOM/window.mozRequestAnimationFramehttp://dev.chromium.org/developers/design-documents/requestanimationframe-implementation

https://developer.mozilla.org/en/DOM/window.mozRequestAnimationFramehttp://dev.chromium.org/developers/design-documents/requestanimationframe-implementation

回答by Luke

I know this is an old question, but it still has no accepted answer.

我知道这是一个老问题,但它仍然没有被接受的答案。

You don't need to have a shorter interval to increase the rate at which your line appears to bend. You keep the interval the same, this is your framerate, and you simply change the stepping between states of the line. It bends more between frames if it is bending quickly.

您不需要更短的间隔来增加您的线似乎弯曲的速度。您保持间隔不变,这是您的帧速率,您只需更改线条状态之间的步进。如果它快速弯曲,它在框架之间弯曲得更多。

Here is an example from something I have been playing around with.

这是我一直在玩的东西的一个例子。

var radius = 0;
var hor = 0;
var frameTime = 1000/60;
var step = 1;

setInterval(function () {
    var draw = document.getElementById('draw');
    var context = draw.getContext('2d');

    draw.width = draw.width;

    context.fillStyle = '#ffffff';
    context.beginPath();
    context.arc(draw.width/2,draw.height/2,radius,0,Math.PI*2,true);
    context.closePath();
    context.stroke();
    context.fill();

    radius = (radius+(step*frameTime))%(draw.height/2);
}, frameTime);

It's a very simple animation, just a circle which grows to the size of the canvas and then starts back from nothing. Here, the variable 'step' controls the rate of the animation. 'frameTime' is the time between frames.

这是一个非常简单的动画,只是一个圆圈,它会增长到画布的大小,然后从无到有。在这里,变量“step”控制动画的速率。'frameTime' 是帧之间的时间。

I hope I have properly understood what the problem is. I know you probably got over it a long time ago, but I thought it best to have an answer here for anybody with a similar problem in future.

我希望我已经正确理解了问题所在。我知道您可能很久以前就已经解决了,但我认为最好在这里为将来遇到类似问题的任何人提供答案。

回答by Ian

I'm not sure if it would work, but try diving a millisecond to break it down further. e.g.

我不确定它是否会起作用,但尝试潜入一毫秒以进一步分解它。例如

setTimeout("moretext()",1 / 100);

setTimeout("moretext()",1 / 100);