requestAnimFrame vs普通的旧settimeout javascript

时间:2012-12-14 00:23:17

标签: javascript ajax settimeout

在脚本上工作,我注意到我的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);
    };
})();

现在google chrome似乎并不关心我在window.setTimeout(回调,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让我知道我是一个菜鸟,并且做错了。帕特里克帮助我清楚地意识到该功能正在发生什么

2 个答案:

答案 0 :(得分:2)

定义功能

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根据定义将具有由客户端确定的帧速率。这意味着它可以每秒运行180x(就像你在chrome中看到的那样)或每秒1x。它允许客户端浏览器确定最重要的内容,并为其提供一种在不需要时关闭屏幕刷新的方法(例如,当选项卡未激活或移动浏览器最小化时)。

答案 1 :(得分:1)

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. 
})();