Chrome不会在需要时重绘页面

时间:2013-05-16 14:47:30

标签: javascript google-chrome

我搜索过类似的问题(e.x. Chrome does not redraw <div> after it is hiddenForce DOM redraw/refresh on Chrome/Mac),但没有一个问题让我解决了我的问题。我正在编写调制解调器配置面板,网页有,标签''。在每个选项卡上都有一些设置 - 就像任何路由器的配置面板一样。

保存配置(当用户点击“保存”按钮时完成)需要几秒钟(我的嵌入式平台不是速度王),所以我决定放置特殊的PLEASE WAIT窗口(div要精确),这通常是隐藏的,但是在需要让用户平静时显示: - )。

Firefox上的一切正常:点击保存后,显示PLEASE WAIT div,然后使用POST方法保存配置。 但是,在Chrome 26和Chromium 25上,div在保存配置之前不会显示。正如您在执行保存配置的PHP脚本后可以在SaveConfiguration函数中看到的那样,警报会显示 - 这是PLEASE WAIT div在Chrome上显示的位置。 看起来Chrome不是重绘页面,但会立即开始启动POST脚本。有没有人有类似的问题,现在如何解决这个问题?

下面是我的代码的片段,我只提供了可能提供我正在做的事情的函数。如果有帮助,我可以发布更多代码。

function showLoadingScreen(yes)
{
    if(yes)
    {
        document.getElementById("loadingtext").innerHTML="Please wait...";
        document.getElementById("loading_overlay").style.display="block";
        document.getElementById("loading_window").style.display="block";
    }
    else
    {
        document.getElementById("loading_overlay").style.display="none";
        document.getElementById("loading_window").style.display="none";
    }
}

function postDataSync(url, params)
{
    var XMLHttpRequestObject = false;
    if (window.XMLHttpRequest) 
    {
        XMLHttpRequestObject = new XMLHttpRequest();
    } else 
        if (window.ActiveXObject) 
        {
            XMLHttpRequestObject = new
            ActiveXObject("Microsoft.XMLHttp");
        }
    if(XMLHttpRequestObject) 
    {
        XMLHttpRequestObject.open("POST", url, false);
        XMLHttpRequestObject.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
        XMLHttpRequestObject.send(params);
        {
            if (XMLHttpRequestObject.readyState == 4 &&
            XMLHttpRequestObject.status == 200) 
            {
                var result = XMLHttpRequestObject.responseText;
                delete XMLHttpRequestObject;
                XMLHttpRequestObject = null;
                return result;
            }
        }
    }
    return '';  
}

function SaveConfiguration()
{
    var errors=checkForm();
    if(errors!="")
    {
        printError("Can't save configuration because there are errors in current tab:<br><br>"+errors);
        return;
    }
    showLoadingScreen(true);
    saveTab();
    var retval=postDataSync('actions/saveconf3.php','');
    alert("Settings saved. The modem is now being reconfigured.");
    document.location = "http://" + retval;
}

2 个答案:

答案 0 :(得分:2)

您正在同步使用ajax而不是异步意味着javascript执行在请求期间暂停。要修复,请进行以下更改:

XMLHttpRequestObject.open("POST", url, true);

您需要在请求完成后对行为使用回调。像这样:

    function postDataSync(url, params, success)
    {
        var XMLHttpRequestObject = false;
        if (window.XMLHttpRequest) 
        {
            XMLHttpRequestObject = new XMLHttpRequest();
        } else 
            if (window.ActiveXObject) 
            {
                XMLHttpRequestObject = new
                ActiveXObject("Microsoft.XMLHttp");
            }
        if(XMLHttpRequestObject) 
        {
            XMLHttpRequestObject.open("POST", url, true);
            XMLHttpRequestObject.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
            XMLHttpRequestObject.send(params);
            XMLHttpRequestObject.onreadystatechange = function() {
                if (XMLHttpRequestObject.readyState == 4 &&
                XMLHttpRequestObject.status == 200) 
                {

    var result = XMLHttpRequestObject.responseText;
                    delete XMLHttpRequestObject;
                    XMLHttpRequestObject = null;
                    if (typeof success === 'function') success(result);
                }
            }
        }
        return '';  
    }

function SaveConfiguration()
{
    var errors=checkForm();
    if(errors!="")
    {
        printError("Can't save configuration because there are errors in current tab:<br><br>"+errors);
        return;
    }
    showLoadingScreen(true);
    saveTab();
    postDataSync('actions/saveconf3.php','', saveComplete);
}

function saveComplete(result) {
  showLoadingScreen(false);
  alert("Settings saved. The modem is now being reconfigured.");
  document.location = "http://" + result;
}

答案 1 :(得分:1)

如果您有大量同步代码(实际上,对数百或数千个已经在内存中的对象进行操作,或者计算pi到数十亿个数字),您可以使用setTimeout为浏览器提供时间来赶上任何渲染任务。您需要为每个任务调用setTimeout,或者如果您有长时间运行的任务,请先批量分割。这需要相当多的重构,因为每个任务都需要表示为可以传递给setTimeout.的函数

我不会同步使用XMLHTTPRequest。

如果setTimeout(fn, 0)没有触发“增量”渲染,请尝试更高的值,直到它起作用。在某些情况下,我认为我需要在作业之间使用100毫秒的值,对于某些浏览器(我不记得是哪个)。

如果你想达到60fps或30fps,你可能需要更快地屈服于浏览器。然后你需要保持在16ms或33ms的每个任务。这在慢速硬件上变得非常紧张,例如(较旧类型的)智能手机。然后,您可以最好使用setTimeout,而不是requestAnimationFrame