【问题标题】:requestAnimFrame vs plain old settimeout javascriptrequestAnimFrame 与普通的旧 settimeout javascript
【发布时间】:2012-12-14 00:23:17
【问题描述】:

在编写脚本时,我注意到我的 ajax 比预期的要多 10 倍,所以我输入了一个“fps 计数器”,并注意到不是像预期的那样每秒运行 10 次,而是每秒运行大约 130 次,即/ff/opera 大约每秒 35 帧。使用以下设置:

function load(){ 
//other code that does not effect this
    requestAnimFrame(function(){
        load();
    });
    debug();//function i was using to catch fps
}

window.requestAnimFrame = (function(callback){
    return window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.oRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    function(callback){
        window.setTimeout(callback, 100);
    };
})();

现在谷歌浏览器似乎并不关心我在 window.setTimeout(callback, 100); 中输入了什么值它可能是 1 也可能是 10000000 它以大约 130 帧的速度运行,而其余的似乎足够接近它(总是大约是预期的 3 倍)并且我已经确保我没有多次调用 load()

另一方面,我曾经使用 setTimeout(load, 100);当我更改为所有浏览器开始以大约 30fps 运行时

function load(){ 
    //other code that does not effect this

        debug();//function i was using to catch fps
        setTimeout(load, 100);
    }

这样做是不好的做法还是过时了?重点是我不太确定为什么我使用 requestAnimFrame,然后我在网上找到的所有示例也都使用它,而且它似乎实现了给定的目标。我一遍又一遍地发射负载的唯一原因是检查并查看是否有任何新信息要下来..

编辑对于那些将来阅读本文的人。通过代码逐行运行后,我发现逻辑错误解释了我的 3x。我确实确保我没有在原地调用 load(),但是

function connected(result){
    if (xmlhttp.readyState==4 && xmlhttp.status==200){
        //code that does not matter for this
    }else if (xmlhttp.status==404){
        alert("epic failure i lost the page");
    }
    d_time = new Date().getTime();
    load();
}

连接被 xmlhttp.onreadystatechange=connected 调用;所以它可以多次运行 3 组 load();我需要做的是:

function connected(result){
    if (xmlhttp.readyState==4 && xmlhttp.status==200){
        d_time = new Date().getTime();
        load();
    }else if (xmlhttp.status==404){
        alert("epic failure i lost the page");
    }

}

所以 schmit 和 patrick 都在这里提供了帮助。施密特让我知道我是一个菜鸟并且做错了。 patrick 帮助我准确了解该函数发生了什么

【问题讨论】:

  • 100 毫秒将是每秒 10 帧...我冒险猜测一下,您的“fps 计数器”代码不正确。
  • 它不是 d_count/(( new Date().getTime() - d_time)/1000) .. d_time 设置为脚本的第一次运行,并且 d_count 是 ++'d 每次 load()运行是我检查的第一件事。此外,它在所有浏览器上运行的代码都相同,因此 chrome 仍然与其他浏览器不同

标签: javascript ajax settimeout


【解决方案1】:

定义函数

window.requestAnimFrame()

这种方式只会在其他函数都不存在的情况下使用 setTimeout。它可以更明确地重写为:

window.requestAnimFrame = (function(callback){
    var theFunction;
    if (window.requestAnimationFrame) {
        theFunction = window.requestAnimationFrame;
    } else if (window.webkitRequestAnimationFrame) {
        theFunction = window.webkitRequestAnimationFrame;
    } else if (window.mozRequestAnimationFrame) {
        theFunction = window.mozRequestAnimationFrame;
    } else if (window.oRequestAnimationFrame) {
        theFunction = window.oRequestAnimationFrame;
    } else if (window.msRequestAnimationFrame) {
        theFunction = window.msRequestAnimationFrame;
    } else {
        theFunction = function(callback){
            window.setTimeout(callback, 100);
        };
    } 
    return theFunction;
})();

所以它只在其他函数都不存在的情况下使用超时。此函数用于在 requestAnimationFrame 不存在的情况下依赖其专有实现,例如在旧浏览器上。那些旧浏览器会使用超时。

根据定义,requestAnimationFrame 的帧率由客户端决定。这意味着它可以每秒运行 180 倍(就像您在 chrome 中看到的那样)或每秒 1 倍。它允许客户端浏览器确定最重要的是什么,并使其在不需要时关闭屏幕刷新的方法(就像选项卡未激活或移动浏览器最小化时)。

【讨论】:

  • 啊,如果我让它在 requestanimframe 上运行,并且在 ajax 上将其限制为不超过每秒 10 次,那将是最好的。这样,如果他们最小化或其他东西,那么 ajax 就不会继续运行? - 害羞,我觉得有点愚蠢,我当时并没有仔细考虑它做了我想要的,然后当我回去看它时,我读错了
  • @Shmiddty,也许我没有,但效果和我写的一样。至少在 javascript 中,||运算符只计算直到它得到一个非假结果(假,“假”,0,“”,空,未定义都是假的)。
  • @NonameProvided 是的,让你的 ajax 调用远离 requestAnimationFrame
【解决方案2】:

http://jsfiddle.net/VMyn8/1/

我相信你的 fps 计时器是错误的。我使用webkitRequestAnimationFrame 获得了一致的 60FPS(实际上是 62 左右)。

var last = new Date(),
    frames = [],
    div = document.getElementById("fps");

(function loop(){
    var span = ((new Date()) - last)/1000;
    last = new Date();
    frames.push(span);

    if (frames.length > 100) frames.shift();

    var total = 0;    
    for (var i = 0; i < frames.length; i++)total += frames[i];    

    div.innerHTML = Math.floor(frames.length/total);
    //setTimeout(loop, 1000/60);
    webkitRequestAnimationFrame(loop);
})();

如果您尝试轮询服务器,我会提出完全不同的建议:

(function poll(){
    // do some stuff

    setTimeout(poll, 3000); // poll every 3 seconds
    // if you are doing an ajax call, you'll want to place the timeout in the 
    // callback so you aren't initiating another call before you've received 
    // a response to the current one. 
})();

【讨论】:

  • 我不知道为什么我的目标是 3 倍,但重要的是获得相同的跨浏览器
  • @NonameProvided 随意删除它们,看看结果是否相同。
  • 已经为你拍了拍自己的脸。但实际上阅读该代码有所帮助..我只需要弄清楚我想如何降低它,这样我就不会向我的服务器/数据库发送垃圾邮件了..对于那些想知道我在上面编辑我的回复的人,它最初说“那是因为你有 -webkit-animation:bounce .5s ease-in-out infinite; 在你的 css 中” Noob 是的......犯了假设并再次发布 b4 检查的错误?没有
  • 是的,这就是我将其更改为的内容。我还编辑了上面的问题,我发现了为什么我的帧数是预期的 3 倍
猜你喜欢
  • 2011-01-02
  • 1970-01-01
  • 1970-01-01
  • 2012-09-25
  • 1970-01-01
  • 1970-01-01
  • 2011-01-16
  • 2022-07-06
  • 2010-10-18
相关资源
最近更新 更多