我试图让一个程序进入页面提示和更新之间的循环。但是,如果我将此问题隔离开来,在本例中为两次追加调用和两次提示,我观察到的行为是页面仅在第二次调用提示后才在视觉上更新。我想这样做的原因是深奥的,但与制作一个“感觉”像用户偶尔输入输入的终端的程序有关。这是一个改编自 w3c 学校的示例,它演示了这个问题:
<!DOCTYPE html>
<html>
<body>
<h1>The Window Object</h1>
<h2>The prompt() Method</h2>
<p>Click the button to demonstrate the prompt box.</p>
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>
<script>
function myFunction() {
let person = prompt("Please enter your name", "Prompt1");
if (person != null) {
document.getElementById("demo").insertAdjacentHTML('beforeend', "Test1\n");
}
person = prompt("Please enter your name", "Prompt2")
if (person != null) {
document.getElementById("demo").insertAdjacentHTML('beforeend', "Test2\n");
}
}
</script>
</body>
</html>
我“希望”发生的是,在第一个 insertAdjacentHTML 调用中,它会更新 DOM,并在页面上可视化地显示第二个提示之前,这样您就可以看到您输入的内容。在实践中,我观察到“Test1 ”和“Test2”在第二次提示后视觉上同时出现。控制台日志记录,与插入相邻调用相反,按我想要的方式工作,但与我正在编写的应用程序无关。
我已经尝试过各种技术来强制解决这个问题(例如,尝试通过滚动调用强制触发布局,使用 requestAnimationFrame),但还没有找到一种技术似乎可以满足我的要求。我的假设(我不确定它是否正确)是在下一帧之前调用第二个提示,这意味着它会阻止任何新的渲染,但这只是一个假设。即使正确,关于如何获得我想要的行为的建议也将不胜感激。
一般来说,我希望观察页面上放置的Test1,然后触发第二个提示调用,然后在Test2之后,假设用户选择了默认值。
使用短超时似乎有效...
function myFunction() {
const d = document.getElementById("demo");
let person = prompt("Please enter your name", "Prompt1");
if (person != null) {
d.insertAdjacentHTML('beforeend', "Test1\n");
}
setTimeout(() => {
person = prompt("Please enter your name", "Prompt2")
if (person != null) {
d.insertAdjacentHTML('beforeend', "Test2\n");
}
}, 50);
}
<h4>Example with setTimeout</h4>
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>
但是如果你需要很多提示,它会很快变得丑陋。如果是这样,也许可以将提示/写入文本/延迟部分包装在一个承诺中并将它们与
then
链接在一起:
function myFunction() {
const d = document.getElementById("demo");
delayPrompt("Please enter your name", "Prompt1", d)
.then(() => delayPrompt("Please enter your name", "Prompt2", d))
.then(() => delayPrompt("something else", "Prompt3", d));
}
async function delayPrompt(text, def, container) {
return new Promise((resolve) => {
let response = prompt(text, def);
if (response != null) {
container.insertAdjacentHTML('beforeend', response);
}
setTimeout(resolve, 50);
});
}
<h4>Example with Promise</h4>
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>