在for循环中使用innerText修改文本导致Chrome浏览器冻结问题求助
问题根源
浏览器的JavaScript执行与UI渲染共享主线程,你的代码存在两处核心问题导致Chrome卡住:
- 使用了
async: false的同步AJAX请求,该特性早已被Web标准弃用,请求过程中会完全阻塞主线程,无法执行任何UI更新操作 - 同步for循环会把所有DOM更新操作缓存,只有当整个循环、所有同步请求都执行完毕后,Chrome才会统一执行UI重绘,因此看不到中间的进度更新。Firefox的内部渲染调度逻辑与Chrome不同,所以才会出现表现不一致的情况,本质属于不规范代码的兼容问题。
解决方案
核心思路是放弃同步AJAX,改用异步逻辑,给主线程留出UI渲染的时间窗,最简洁的改造方案是使用async/await实现异步串行执行:
<!DOCTYPE html> <html> <head> <title>Hello</title> <meta charset="utf-8"/> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> </head> <body> <h1 id="a">Hello!</h1> </body> <script type="text/javascript"> // 改为async异步函数 async function initTrs(){ // 用let代替var避免变量提升问题 for(let i = 1; i<=100; i++){ document.getElementById("a").innerText = i; // await异步AJAX请求,默认async为true,让出主线程给浏览器执行UI重绘 await $.ajax({ url: "https://www.google.com", }).catch(err => { // 可自行添加请求异常处理逻辑 console.log(err) }); } } window.addEventListener("load", () => initTrs()); </script> </html>
改造后每次更新进度文本后,浏览器都会在等待AJAX响应的空闲时间执行UI重绘,就能正常看到进度变化,同时不会阻塞页面交互。
如果确实需要兼容不支持async/await的旧环境,可以用递归+setTimeout的方式实现,每次循环间隔留给浏览器重绘时间即可。
内容的提问来源于stack exchange,提问作者Rudy Grinberg
相关产品推荐
相关产品推荐

