英文:
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.
<!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>
答案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;
};
英文:
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("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();
<!-- language: lang-html -->
<p id="Display"></p>
<!-- end snippet -->
Put your algorithm in a JS file where it posts a message when it wants an update
for (let i = 0; i <= 3000000000; i++) {
if (i % 100000000 == 0) self.postMessage(i);
}
and in your UI code.
const display = document.getElementById("Display");
const myWorker = new Worker("workerAlgorithm.js");
myWorker.onmessage = (e) => {
display.innerHTML = e.data;
};
答案2
得分: 1
如 @epascarello 在评论中提到的,使用工作线程(worker) 是处理计算任务的传统方式之一,以便在主线程之外执行,以防止阻塞渲染。以下是一个简单的示例,您可以使用它进行复制。
> 看起来 Stack Overflow 不会在片段中执行来自 blob URL 的工作线程脚本,因此您需要将代码保存为本地 HTML 文件,使用本地 HTTP 服务器提供它,并在浏览器中导航到它。这里有一个公开托管示例的链接: https://jsfiddle.net/zsb7cou5/
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>在单独的线程上计算</title>
<script type="module">
const display = document.getElementById("Display");
const workerScriptSource = `
for (let i = 0; i <= 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: "text/javascript" }),
);
const worker = new Worker(workerScriptUrl, { type: "module" });
worker.addEventListener("message", (ev) => {
display.textContent = ev.data;
});
</script>
</head>
<body>
<p id="Display"></p>
</body>
</html>
英文:
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/
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Compute on a separate thread</title>
<script type="module">
const display = document.getElementById("Display");
const workerScriptSource = `
for (let i = 0; i <= 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: "text/javascript" }),
);
const worker = new Worker(workerScriptUrl, { type: "module" });
worker.addEventListener("message", (ev) => {
display.textContent = ev.data;
});
</script>
</head>
<body>
<p id="Display"></p>
</body>
</html>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论