我搜索过类似的问题(e.x. Chrome does not redraw <div> after it is hidden和Force 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;
}
答案 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
。