JavaScript中如何在长时间循环周期内刷新/重绘元素文本?
问题根源
JavaScript采用单线程模型,UI渲染与JS代码执行共用主线程。当你同步执行longTimeFunction这类耗时任务时,浏览器会优先跑完所有同步JS代码,再统一进行UI渲染。所以你修改的innerText会被积压,直到foo()完全执行完毕才会一次性更新到页面,导致看不到中间状态变化。
可行解决方案
方案1:用setTimeout拆分同步任务
把耗时任务丢进setTimeout,让UI渲染能插入到任务间隙:
function longTimeFunction() { for (let i = 0; i < 100000000; i++) { // do something } } function foo() { const myDiv = document.getElementById('mydiv'); myDiv.innerText = 'Start'; console.log(myDiv.innerText); setTimeout(() => { longTimeFunction(); myDiv.innerText = 'First call complete'; console.log(myDiv.innerText); setTimeout(() => { longTimeFunction(); myDiv.innerText = 'Second call complete'; console.log(myDiv.innerText); }, 0); }, 0); } foo();
方案2:用requestAnimationFrame触发UI渲染
借助requestAnimationFrame确保UI更新后再执行耗时任务:
function longTimeFunction() { for (let i = 0; i < 100000000; i++) { // do something } } function foo() { const myDiv = document.getElementById('mydiv'); myDiv.innerText = 'Start'; console.log(myDiv.innerText); requestAnimationFrame(() => { longTimeFunction(); myDiv.innerText = 'First call complete'; console.log(myDiv.innerText); requestAnimationFrame(() => { longTimeFunction(); myDiv.innerText = 'Second call complete'; console.log(myDiv.innerText); }); }); } foo();
方案3:用Web Worker(适合大量计算场景)
把耗时任务移到Web Worker中,彻底避免阻塞主线程:
主线程代码
function foo() { const myDiv = document.getElementById('mydiv'); const worker = new Worker('worker.js'); myDiv.innerText = 'Start'; console.log(myDiv.innerText); worker.postMessage('first'); worker.onmessage = function(e) { if (e.data === 'firstDone') { myDiv.innerText = 'First call complete'; console.log(myDiv.innerText); worker.postMessage('second'); } else if (e.data === 'secondDone') { myDiv.innerText = 'Second call complete'; console.log(myDiv.innerText); worker.terminate(); } }; } foo();
worker.js文件
self.onmessage = function(e) { if (e.data === 'first' || e.data === 'second') { for (let i = 0; i < 100000000; i++) { // do something } self.postMessage(`${e.data}Done`); } };
补充说明
你之前尝试的修改样式、切换display等操作无效,是因为这些同样属于UI更新,都会被同步JS阻塞,必须打破同步阻塞的流程,让UI渲染有机会在耗时任务之间执行。
内容的提问来源于stack exchange,提问作者denissaha
相关产品推荐
相关产品推荐

