如何在JavaScript中强制实时显示更新?

huangapple go评论69阅读模式
英文:

How to force real-time display updates in javascript?

问题

如何让 JavaScript 实时更新我的网页?
似乎我的 Chrome 浏览器将所有处理工作都集中在必要的计算上,然后再进行网页更新。下面是最简单的测试 HTML 文件。我希望看到顺序计数(而不仅仅是跳到最终值)。我应该用什么替换 display.innerHTML = i;

我希望答案不是将我的计算拆分为许多计算,使用 setInterval 或类似的东西。当然,这些间断会允许显示更新,但我宁愿不要处理得如此详细...我希望有一个可用的“阻塞”显示函数,这样这里的计数将不会继续,直到浏览器呈现我的显示更新(或者是否有像 C 提供的“flush”命令?)。如果需要的话,我可以使用开发者控制台,但那也不是理想的选择。

<!DOCTYPE html>
<html>
<body>
<p id="Display"></p>
<script>
const display  = document.getElementById("Display");
for (let i = 0; i <= 3000000000; i++) {
    if (i % 100000000 == 0) display.innerHTML = i;
}
</script>
</body>
</html>
英文:

How can I get javascript to update my webpage in real-time?
It seems that my Chrome browser puts all of its processing effort into required computations, and then does the webpage updates. Below is the simplest test HTML file. I would prefer to see sequential counting (instead of just one jump to the final value). What should I replace display.innerHTML = i; with?

I hope the answer is not to break up my computation into many computations using setInterval or something like that. Of course, the breaks this creates will allow display updates, but I prefer not to manage it in such detail...I am hoping that there is a "blocking" display function available, so that the count here will not proceed until the browser renders my display update (or is there is a "flush" command like C provides?). I could use the developer console if needed, but that is also not ideal.

&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;body&gt;
&lt;p id=&quot;Display&quot;&gt;&lt;/p&gt;
&lt;script&gt;
const display  = document.getElementById(&quot;Display&quot;);
for (let i = 0; i &lt;= 3000000000; i++) {
            if (i %   100000000 == 0) display.innerHTML = i; }
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

答案1

得分: 2

requestAnimationFrame 的方式

使用 requestAnimationFrame 或 setTimeout,其中你退出循环以允许 UI 进行更新,然后在你离开的地方继续循环。

const display = document.getElementById("Display");

function process() {

  let index = 0;
  const max = 3000000000;
  
  function run () { 
    while (index <= max) {
      if (index % 100000000 == 0) {
        display.innerHTML = index;
        break;
      }
      index++;
    }
    if (index++ <= max) window.requestAnimationFrame(run);
  }
  
  run();
}

process();
<p id="Display"></p>

Web Worker 的方式

将你的算法放在一个 JS 文件中,在需要更新时发送一条消息:

for (let i = 0; i <= 3000000000; i++) {
    if (i % 100000000 == 0) self.postMessage(i);
}

然后在你的 UI 代码中:

const display  = document.getElementById("Display");
const myWorker = new Worker("workerAlgorithm.js");
myWorker.onmessage = (e) => {
  display.innerHTML = e.data;
};

Web Worker 的方式

英文:

requestAnimationFrame way

Using requestAnimationFrame or setTimeout where you exit the loop to let it allow the UI to be updated and you resume the loop where you left off.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const display = document.getElementById(&quot;Display&quot;);

function process() {

  let index = 0;
  const max = 3000000000;
  
  function run () { 
    while (index &lt;= max) {
      if (index % 100000000 == 0) {
        display.innerHTML = index;
        break;
      }
      index++;
    }
    if (index++ &lt;= max) window.requestAnimationFrame(run);
  }
  
  run();
}

process();

<!-- language: lang-html -->

&lt;p id=&quot;Display&quot;&gt;&lt;/p&gt;

<!-- end snippet -->


The web worker way

Put your algorithm in a JS file where it posts a message when it wants an update

for (let i = 0; i &lt;= 3000000000; i++) {
    if (i %   100000000 == 0) self.postMessage(i);
}

and in your UI code.

const display  = document.getElementById(&quot;Display&quot;);
const myWorker = new Worker(&quot;workerAlgorithm.js&quot;);
myWorker.onmessage = (e) =&gt; {
  display.innerHTML = e.data;
};

答案2

得分: 1

@epascarello 在评论中提到的,使用工作线程(worker) 是处理计算任务的传统方式之一,以便在主线程之外执行,以防止阻塞渲染。以下是一个简单的示例,您可以使用它进行复制。

> 看起来 Stack Overflow 不会在片段中执行来自 blob URL 的工作线程脚本,因此您需要将代码保存为本地 HTML 文件,使用本地 HTTP 服务器提供它,并在浏览器中导航到它。这里有一个公开托管示例的链接: https://jsfiddle.net/zsb7cou5/

&lt;!doctype html&gt;
&lt;html lang=&quot;en&quot;&gt;

&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;

  &lt;title&gt;在单独的线程上计算&lt;/title&gt;

  &lt;script type=&quot;module&quot;&gt;
    const display = document.getElementById(&quot;Display&quot;);
    
    const workerScriptSource = `
    for (let i = 0; i &lt;= 3_000_000_000; i += 1) {
      if (i % 100_000_000 === 0) self.postMessage(i);
    }
    self.close();
    `;

    const workerScriptUrl = URL.createObjectURL(
      new Blob([workerScriptSource], { type: &quot;text/javascript&quot; }),
    );
    
    const worker = new Worker(workerScriptUrl, { type: &quot;module&quot; });
    
    worker.addEventListener(&quot;message&quot;, (ev) =&gt; {
      display.textContent = ev.data;
    });
    
    &lt;/script&gt;
&lt;/head&gt;

&lt;body&gt;
  &lt;p id=&quot;Display&quot;&gt;&lt;/p&gt;
&lt;/body&gt;

&lt;/html&gt;

英文:

As @epascarello mentioned in a comment, using a worker is the conventional way to handle computational tasks off of the main thread — in order to prevent blocking renders. Below is a simple example that you can use to reproduce.

> It appears that Stack Overflow won't execute worker scripts from blob URLs in snippets, so you'll need to save the code as a local HTML file, serve it with a local http server, and navigate to it in your browser. Here's a link to a publicly hosted copy of the example: https://jsfiddle.net/zsb7cou5/

&lt;!doctype html&gt;
&lt;html lang=&quot;en&quot;&gt;

&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;

  &lt;title&gt;Compute on a separate thread&lt;/title&gt;

  &lt;script type=&quot;module&quot;&gt;
    const display = document.getElementById(&quot;Display&quot;);
    
    const workerScriptSource = `
    for (let i = 0; i &lt;= 3_000_000_000; i += 1) {
      if (i % 100_000_000 === 0) self.postMessage(i);
    }
    self.close();
    `;

    const workerScriptUrl = URL.createObjectURL(
      new Blob([workerScriptSource], { type: &quot;text/javascript&quot; }),
    );
    
    const worker = new Worker(workerScriptUrl, { type: &quot;module&quot; });
    
    worker.addEventListener(&quot;message&quot;, (ev) =&gt; {
      display.textContent = ev.data;
    });
    
    &lt;/script&gt;
&lt;/head&gt;

&lt;body&gt;
  &lt;p id=&quot;Display&quot;&gt;&lt;/p&gt;
&lt;/body&gt;

&lt;/html&gt;

huangapple
  • 本文由 发表于 2023年7月14日 02:32:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76682327.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定