0

我已经搜索过类似的问题(例如Chrome 在隐藏后不会重绘 <div>在 Chrome/Mac 上强制 DOM 重绘/刷新),但没有一个问题能解决我的问题。我正在编写调制解调器配置面板,带有 ,,tabs'' 的网页。在每个选项卡上都有一些设置 - 就像任何路由器的配置面板一样。

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

在 Firefox 上一切正常:点击保存后,请等待 div 显示,然后使用 POST 方法保存配置。但是,在 Chrome 26 和 Chromium 25 上,在保存配置之前 div 不会显示。正如您SaveConfiguration在执行保存配置的 PHP 脚本后在函数中看到的那样,会显示警报 - 这是 Chrome 上显示 PLEASE WAIT div 的位置。看起来 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;
}
4

2 回答 2

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;
}
于 2013-05-16T14:54:12.077 回答
1

如果您有繁重的同步代码(实际上,对内存中的数百或数千个对象进行操作,或者将 pi 计算到无数位),您可以使用setTimeout让浏览器有时间赶上任何渲染任务。您需要setTimeout为每个任务调用,或者如果您有一个长时间运行的任务,请先将其分批。不过,这需要进行相当多的重构,因为每个任务都需要表示为可以传递给setTimeout.

我永远不会同步使用 XMLHTTPRequest。

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

如果您想达到 60fps 或 30fps,您可能需要更快地屈服于浏览器。然后,您需要将每个任务的时间控制在 16 毫秒或 33 毫秒以下。这在慢速硬件上变得非常严格,例如(旧类型的)智能手机。然后,如果可用setTimeout,您最好使用代替。requestAnimationFrame

于 2013-05-16T15:18:35.207 回答