有没有办法强制 DOM 在重复调用 JavaScript 提示之间更新?

问题描述 投票:0回答:1

我试图让一个程序进入页面提示和更新之间的循环。但是,如果我将此问题隔离开来,在本例中为两次追加调用和两次提示,我观察到的行为是页面仅在第二次调用提示后才在视觉上更新。我想这样做的原因是深奥的,但与制作一个“感觉”像用户偶尔输入输入的终端的程序有关。这是一个改编自 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之后,假设用户选择了默认值。

javascript dom prompt
1个回答
0
投票

使用短超时似乎有效...

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>

© www.soinside.com 2019 - 2024. All rights reserved.