为什么多个setTimeout()调用导致如此之多的滞后? [英] Why do multiple setTimeout() calls cause so much lag?

查看:171
本文介绍了为什么多个setTimeout()调用导致如此之多的滞后?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个复杂的动画序列,涉及JavaScript中的淡入淡出和转换。在这个由四个元素组成的序列中,每个元素都使用一个 setTimeout

测试在Internet Explorer 9中,动画以实时的速度运行(应该需要1.6秒,精确到1.6秒)。任何其他浏览器将会滞后,动画时间为4秒(Firefox 3和4,Chrome,Opera)以及类似于IE 8及以下版本的20秒。

如何才能IE9走得这么快,而所有其他浏览器都陷入泥潭?

我试图找到合并元素的方法之一,所以在任何时候都有一个setTimeout,但不幸的是它不能承受任何干扰(比如点击不同的链接在当前播放完成之前开始一个新的动画)。

编辑:要详细说明回应的意见,下面是代码大纲:

 链接。 onclick = function(){
clearTimeout(colourFadeTimeout);
colourFadeTimeout = setTimeout(colourFade(0);,25);

clearTimeout(arrowScrollTimeout);
arrowScrollTimeout = setTimeout(arrowScroll(0);,25);

clearTimeout(pageFadeOutTimeout);
pageFadeOutTimeout = setTimeout(pageFadeOut(0);,25);

clearTimeout(pageFadeInTimeout);
pageFadeInTimeout = setTimeout(pageFadeIn(0);,25);

$



这四个函数中的每一个函数都会将淡入淡出一帧,然后设置另一个超时直到动画结束。



你可以在 http://adamhaskell.net/cw/index.html (用户名:knockknock;密码:goaway)(它有声音和音乐,可以禁用,但要警告! ) - 我的JavaScript非常混乱,因为我没有真正地组织它,但它有点评论,所以希望你能看到一般的想法是什么。

解决方案

几件事情:


  1. 您的超时时间是25ms。这转换为40fps这是一个非常高的帧率,尝试通过JavaScript实现。特别是对涉及DOM操作的事件,可能会触发回流。把它增加到50或60。对于你正在做的动画来说,15fps应该足够流畅。不要在这里显示视频,只要在页面上移动即可。

  2. >的setTimeout()
    。特别是如果你关心性能。这将强制javascript重新编译字符串的每帧动画。改用一个函数。如果您需要传递参数,请使用匿名函数来包装要执行的函数:

      setTimeout(function(){ 
    pageFadeIn(0)
    },50);

    这个只会在脚本加载时编译一次。

    $正如Ben所提到的那样,使用一个setTimeout来调度函数会更便宜。对于这个问题,代码的清晰度可以通过使用setInterval来改善(或者不能,取决于你的编码风格)。


    hr>

    附加答案: b
    $ b

    编程的javascript动画是所有关于优化和折中的。可以在页面上动画很多东西,但是你需要知道如何正确地做,并决定要牺牲什么。作为一个例子,一次可以做多少动画是我几年前写的一个演示实时策略游戏。

    在我做的优化游戏是:


    1. 行走的士兵只有两个动画帧,我只是在两个图片之间切换。但效果是非常令人信服的。你不需要完美的动画,只是一个看起来令人信服的动画。

    2. 我使用一个setInterval的一切。这是更便宜的CPU和更容易管理。只要决定一个基本帧率,然后安排不同的动画在不同的时间开始。



    I have a complex animation sequence involving fades and transitions in JavaScript. During this sequence, which consists of four elements changing at once, a setTimeout is used on each element.

    Tested in Internet Explorer 9, the animation works at realtime speed (it should take 1.6 seconds and it took exactly 1.6 seconds). ANY other browser will lag horribly, with animation times of 4 seconds (Firefox 3 and 4, Chrome, Opera) and something like 20 seconds in IE 8 and below.

    How can IE9 go so fast while all other browsers are stuck in the mud?

    I have tried to find ways of merging the elements into one, so as to one have one setTimeout at any given time, but unfortunately it wouldn't stand up to any interference (such as clicking a different link to start a new animation before the current one has finished).

    EDIT: To elaborate in response to comments, here's the outline of the code:

    link.onclick = function() {
        clearTimeout(colourFadeTimeout);
        colourFadeTimeout = setTimeout("colourFade(0);",25);
    
        clearTimeout(arrowScrollTimeout);
        arrowScrollTimeout = setTimeout("arrowScroll(0);",25);
    
        clearTimeout(pageFadeOutTimeout);
        pageFadeOutTimeout = setTimeout("pageFadeOut(0);",25);
    
        clearTimeout(pageFadeInTimeout);
        pageFadeInTimeout = setTimeout("pageFadeIn(0);",25);
    }
    

    Each of the four functions progress the fade by one frame, then set another timeout with the argument incremented, until the end of the animation.

    You can see the page at http://adamhaskell.net/cw/index.html (Username: knockknock; Password: goaway) (it has sound and music, which can be disabled, but be warned!) - my JavaScript is very messy since I haven't really organised it properly, but it is commented a bit so hopefully you can see what the general idea is.

    解决方案

    Several things:

    1. Your timeout is 25ms. This translates to 40fps which is a very high framerate to try to achieve via javascript. Especially for things involving DOM manipulation that may trigger reflows. Increase it to 50 or 60. 15fps should be more than fluid enough for the kinds of animation you're doing. You're not trying to display videos here, just move things around the page.

    2. Don't use strings as the first parameter to setTimeout(). Especially if you care about performance. That will force javascript to recompile the string each frame of animation. Use a function instead. If you need to pass an argument use an anonymous function to wrap the function you want to execute:

      setTimeout(function(){
          pageFadeIn(0)
      },50);
      

      this will only get compiled once when the script is loaded.

    3. As mentioned by Ben, it is cheaper to use a single setTimeout to schedule the functions. For that matter, code clarity may improve by using setInterval instead (or it may not, depends on your coding style).


    Additional answer:

    Programming javascript animation is all about optimisation and compromise. It's possible to animate lots of things on the page with little slow-down but you need to know how to do it right and decide what to sacrifice. As an example of just how much can be animated at once is a demo real-time strategy game I wrote a couple of years ago.

    Among the things I did to optimize the game are:

    1. The walking soldiers are made up of only two frames of animation and I simply toggle between the two images. But the effect is very convincing nonetheless. You don't need perfect animation, just one that looks convincing.

    2. I use a single setInterval for everything. It's cheaper CPU-wise and easier to manage. Just decide on a base frame rate and then schedule for different animation to start at different times.

    这篇关于为什么多个setTimeout()调用导致如此之多的滞后?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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