为什么在javascript中不更新异步函数的UI
我有一个浏览器应用程序,我想更改UI中的一些文本以表示页面正在加载,然后运行一个长过程,一旦过程完成,则表示页面已完成加载 使用下面编写的代码,我可以在调用为什么在javascript中不更新异步函数的UI,javascript,asynchronous,Javascript,Asynchronous,我有一个浏览器应用程序,我想更改UI中的一些文本以表示页面正在加载,然后运行一个长过程,一旦过程完成,则表示页面已完成加载 使用下面编写的代码,我可以在调用ProperlyUpdatesUIAsync时实现这一点,在长流程运行时文本会发生更改,然后一旦长流程完成,它会再次更改以指示已完成 但是,当我使用doesNotupDateUIUntellendAsync方法时,直到长过程完成后,UI才会更新,从未显示“加载”消息 我是否误解了async/await如何使用JavaScript?为什么它在一
ProperlyUpdatesUIAsync
时实现这一点,在长流程运行时文本会发生更改,然后一旦长流程完成,它会再次更改以指示已完成
但是,当我使用doesNotupDateUIUntellendAsync
方法时,直到长过程完成后,UI才会更新,从未显示“加载”消息
我是否误解了async
/await
如何使用JavaScript?为什么它在一种情况下有效,而在另一种情况下无效
async function ProperlyUpdatesUIAsync(numberOfImagesToLoad) {
$("#PageStatusLabel").text("Loading..");
await pauseExecutionAsync(2000);
$("#PageStatusLabel").text("Loaded");
}
// this method doesn't do anything other than wait for the specified
// time before allowing execution to continue
async function pauseExecutionAsync(timeToWaitMilliseconds) {
return new Promise(resolve => {
window.setTimeout(() => {
resolve(null);
}, timeToWaitMilliseconds);
});
}
async function DoesNotUpdateUIUntilEndAsync(numberOfImagesToLoad) {
$("#PageStatusLabel").text("Loading..");
await runLongProcessAsync();
$("#PageStatusLabel").text("Loaded");
}
async function runLongProcessAsync() {
// there is a for loop in here that takes a really long time
}
编辑:
我尝试了一些东西,这个新的重构给了我想要的结果,但我不喜欢它。我将长时间运行的循环包装在一个设置为10的setTimeout中。如果值为10,则在运行循环之前更新UI。但是,值为0甚至1都不允许UI更新,并且它的行为仍然像根本没有声明超时一样。10似乎太武断了。我真的可以在每种情况下都依靠它吗?异步/等待是否应该在UI更新之前延迟执行,而不必在超时中包装所有内容
async function runLongProcessThatDoesNotBlockUIAsync() {
return new Promise(resolve => {
window.setTimeout(() => {
// there is a for loop in here that takes a really long time
resolve(null);
}, 10);
});
}
编辑
runLongProcessAsync()中的代码从不删除/放弃线程以进行更新
尝试:-
<!DOCTYPE html>
<html>
<script type="text/javascript">
var keep;
async function DoesNotUpdateUIUntilEndAsync(numberOfImagesToLoad) {
document.getElementById("PageStatusLabel").innerHTML="Loading..";
p = new Promise((resolve) => {keep = resolve})
setTimeout(theRest,0); //let the Loading message appear
return p;
}
async function theRest(){
await runLongProcessAsync(); // Your await here is useless!
document.getElementById("PageStatusLabel").innerHTML="Loaded";
keep();
}
async function runLongProcessAsync() {
// there is a for loop in here that takes a really long time
for (var x=1; x<1000000000;x++){b=x^2}
}
</script>
<body onload="DoesNotUpdateUIUntilEndAsync(5)">
<p>Test</p>
<p id="PageStatusLabel"></p>
</body>
</html>
var保持;
异步函数不使用TupDateUIUntilendAsync(numberOfImagesToLoad){
document.getElementById(“PageStatusLabel”).innerHTML=“加载..”;
p=新承诺((解析)=>{keep=resolve})
setTimeout(theRest,0);//显示加载消息
返回p;
}
异步函数theRest(){
wait runLongProcessAsync();//此处的等待没有用!
document.getElementById(“PageStatusLabel”).innerHTML=“Loaded”;
保持();
}
异步函数runLongProcessAsync(){
//这里有一个for循环,需要很长时间
对于(var x=1;x您想问的问题是“JavaScript的事件循环是如何工作的?”有很多很好的博客文章和视频可以解释这个主题。这是一个非常好的话题,可以很好地解释这个主题。作为一个健全性检查,您可以console.log(document.querySelectorAll('#PageStatusLabel'))
在的开头,DoesNotUpdateUIUntilEndAsync
以确保页面上确实存在具有该ID的元素。看起来您正在使用jQuery,如果元素丢失,它不会出错。“Promise(;)”的语法是什么?如果在()中有分号,则会出现解析错误,但如果我将其更改为“Promise()”,然后执行在该行停止,并且永远不会继续。很抱歉,这更多是伪代码,而不是代码,但您的想法是正确的?您的runLongProcessAsync()只是名义上是异步的。你能告诉我实际的代码吗?如果你用Ajax加载图像,那么我错了,但我怀疑你的POC代码正在同步占用主线程,阻止UI更新。长时间运行的进程肯定占用线程,这会阻塞UI。我希望UI一旦进入该方法就会被阻塞,但因为如果该方法标记为async,我希望等待之前的代码在进入长阻塞过程之前有机会呈现。请查看我对原始帖子所做的编辑。我发现,如果我在启动阻塞代码之前等待10毫秒,UI会呈现,但如果我只等待1毫秒,则不会呈现。T不过,他的作品似乎过于武断,无法在制作中依靠。