JavaScript 慢 DOM 更新
JavaScript Slow DOM Update
我目前正在从事一个电子项目,在该项目的一部分中,我想递归地查找目录中的文件,并像 winrar 一样向用户显示每个文件名。
你们都知道 winrar 在我们存档或取消存档时是如何工作的,文件名快速显示,进度条向前移动。这与我正在尝试做的非常相似。见下图。
现在的问题是,当 electron 递归扫描目录时,它会一个接一个地查找文件,然后在控制台中打印文件名,但不会在 DOM 中打印。如果扫描时间过长,这种情况会使用户认为程序无法正常工作。在扫描程序结束时,在所有扫描操作完成后向用户显示最后一个文件名。
出于这个原因,我编写了一个示例代码来在浏览器中快速更新 DOM,我在我的电子项目中遇到了同样的问题。我怎样才能克服这个问题,我以前从未见过这样的事情,为什么会这样,请解释一下。
示例代码在这里。将数字增加到 10000 并在浏览器中尝试以更好地理解。
var myBtn = document.getElementById('myBtn');
var myDiv = document.getElementById('myDiv');
myBtn.addEventListener('click', function() {
for (var i = 0; i < 1000; i++) {
myDiv.innerHTML = i;
console.log(i);
}
});
#myDiv {
border: 1px solid black;
padding: 30px;
margin-bottom: 10px;
}
#myBtn {
padding: 10px;
}
<div id="myDiv"></div>
<button id="myBtn" type="button" name="button">Button</button>
为了了解发生了什么,您需要了解事件循环的工作原理。因为 JS 是一种单线程语言,各个代码单元(称为“任务”)轮流执行,但永远不能中断另一个。这就是为什么您的代码不起作用的原因。主线程卡在那个循环上,在完成之前不能做任何其他事情。
您可以使用 window.requestAnimationFrame()
为文本添加动画效果,但您可能应该显示当前正在处理的文件,WinRar 就是这样做的。
const outDiv = document.getElementById("output");
// The each number is displayed. (lower = faster)
const PERIOD = 50;
// The limit.
const MAX = 100;
// The code is written like this so it always runs
// at the same speed. Never increment `i` in the
// handler!
let startTime = performance.now();
function handler(now) {
const timeDiff = (now - startTime),
i = Math.min(Math.floor(timeDiff / PERIOD), MAX);
outDiv.innerText = i;
if (i < MAX) {
window.requestAnimationFrame(handler);
}
}
handler(startTime);
<div id="output"></div>
我目前正在从事一个电子项目,在该项目的一部分中,我想递归地查找目录中的文件,并像 winrar 一样向用户显示每个文件名。
你们都知道 winrar 在我们存档或取消存档时是如何工作的,文件名快速显示,进度条向前移动。这与我正在尝试做的非常相似。见下图。
现在的问题是,当 electron 递归扫描目录时,它会一个接一个地查找文件,然后在控制台中打印文件名,但不会在 DOM 中打印。如果扫描时间过长,这种情况会使用户认为程序无法正常工作。在扫描程序结束时,在所有扫描操作完成后向用户显示最后一个文件名。
出于这个原因,我编写了一个示例代码来在浏览器中快速更新 DOM,我在我的电子项目中遇到了同样的问题。我怎样才能克服这个问题,我以前从未见过这样的事情,为什么会这样,请解释一下。
示例代码在这里。将数字增加到 10000 并在浏览器中尝试以更好地理解。
var myBtn = document.getElementById('myBtn');
var myDiv = document.getElementById('myDiv');
myBtn.addEventListener('click', function() {
for (var i = 0; i < 1000; i++) {
myDiv.innerHTML = i;
console.log(i);
}
});
#myDiv {
border: 1px solid black;
padding: 30px;
margin-bottom: 10px;
}
#myBtn {
padding: 10px;
}
<div id="myDiv"></div>
<button id="myBtn" type="button" name="button">Button</button>
为了了解发生了什么,您需要了解事件循环的工作原理。因为 JS 是一种单线程语言,各个代码单元(称为“任务”)轮流执行,但永远不能中断另一个。这就是为什么您的代码不起作用的原因。主线程卡在那个循环上,在完成之前不能做任何其他事情。
您可以使用 window.requestAnimationFrame()
为文本添加动画效果,但您可能应该显示当前正在处理的文件,WinRar 就是这样做的。
const outDiv = document.getElementById("output");
// The each number is displayed. (lower = faster)
const PERIOD = 50;
// The limit.
const MAX = 100;
// The code is written like this so it always runs
// at the same speed. Never increment `i` in the
// handler!
let startTime = performance.now();
function handler(now) {
const timeDiff = (now - startTime),
i = Math.min(Math.floor(timeDiff / PERIOD), MAX);
outDiv.innerText = i;
if (i < MAX) {
window.requestAnimationFrame(handler);
}
}
handler(startTime);
<div id="output"></div>