0

0

如何在 JavaScript 循环中实时更新 HTML 进度条 UI

心靈之曲

心靈之曲

发布时间:2026-02-15 11:00:12

|

557人浏览过

|

来源于php中文网

原创

如何在 JavaScript 循环中实时更新 HTML 进度条 UI

javascript 同步循环会阻塞浏览器渲染,导致进度条无法及时刷新;本文介绍使用 async/await + 自定义 sleep 函数将密集计算“切片”执行,让出主线程控制权,实现平滑、可响应的 ui 更新。

javascript 同步循环会阻塞浏览器渲染,导致进度条无法及时刷新;本文介绍使用 async/await + 自定义 sleep 函数将密集计算“切片”执行,让出主线程控制权,实现平滑、可响应的 ui 更新。

在 Web 开发中,常需在执行耗时任务(如批量图像上传、数据处理)时动态更新进度条。但若直接在 for 循环中修改 DOM(如设置 element.style.width),浏览器不会立即重绘——因为 JS 执行与渲染共用单线程,且渲染通常发生在 JS 脚本执行完毕后的空闲帧(frame)。因此,你看到的“进度条卡住直到循环结束才跳到 100%”,本质是渲染被同步脚本完全阻塞。

解决的关键在于:主动让出主线程控制权,使浏览器有机会执行样式计算、布局和绘制。现代最佳实践是避免 setTimeout 或 setInterval 嵌套管理状态,转而采用 async/await 配合微任务调度,代码更清晰、可控性更强。

以下是一个可直接运行的完整解决方案:

Lemonaid
Lemonaid

AI音乐生成工具,在音乐领域掀起人工智能革命

下载
async function upload_img() {
  const progressBar = document.querySelector("#progress-bar");
  const barArea = document.querySelector("#bar-area");
  barArea.style.display = "flex";

  // 模拟原始数据结构(实际项目中替换为真实 obj_data)
  const obj_data = Array.from({ length: 100 }, () => Array(134).fill(0));
  const size = obj_data.length * obj_data[0].length;

  // ✅ 核心:定义非阻塞延时函数
  const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

  let j = 0;
  for (let row = 0; row < obj_data.length; row++) {
    for (let col = 0; col < obj_data[0].length; col++) {
      j++;

      // 每处理 1000 项或到达终点时更新 UI(可根据性能调整频率)
      if (j % 1000 === 0 || j === size) {
        const percent = Math.round((j / size) * 100);
        progressBar.style.width = `${percent}%`;
        console.log(`${j} / ${size} → ${percent}%`);
      }

      // ⚠️ 关键:每轮迭代后暂停 5–20ms,释放主线程
      // 浏览器在此间隙完成重排(reflow)与重绘(repaint)
      await sleep(10);
    }
  }
}

配套 HTML/CSS 示例(确保结构匹配):

立即学习Java免费学习笔记(深入)”;

<!-- 进度条容器 -->
<div id="bar-area" style="display: none;">
  <div id="progress-bar" style="
    height: 24px;
    background: #e0e0e0;
    border-radius: 12px;
    overflow: hidden;
  "></div>
</div>
#progress-bar {
  width: 0%;
  background: linear-gradient(90deg, #4a90e2, #6a5acd);
  transition: width 0.3s ease; /* 添加平滑过渡效果 */
}

注意事项与优化建议:

  • 避免过短延时:sleep(0) 不可靠(可能被合并进同一帧),推荐 5–20ms;过小(如 1ms)仍可能导致卡顿,过大则进度感迟滞。
  • 按需节流更新:高频 DOM 操作本身有开销,示例中 j % 1000 是合理节流策略,实际可根据总任务量动态调整(例如 Math.max(1, Math.floor(size / 50)))。
  • 错误处理与中断支持:生产环境应包裹 try/catch,并考虑添加 AbortController 支持用户取消操作。
  • 替代方案对比
    • requestIdleCallback:适合后台低优先级任务,但不保证及时性;
    • Web Workers:彻底移出主线程,适用于纯计算(无 DOM 操作),但需消息通信;
    • setTimeout(..., 0) 循环:可行但状态管理复杂,易出错;async/await 是更简洁、可读性更高的现代替代。

调用时只需 upload_img() 即可启动带实时反馈的上传流程。该模式不仅适用于进度条,也广泛用于分步表单验证、动画序列、大数据可视化等需要“呼吸感”的交互场景。

相关文章

HTML速学教程(入门课程)
HTML速学教程(入门课程)

HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

673

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

673

2023.08.10

go语言 数组和切片
go语言 数组和切片

本专题整合了go语言数组和切片的区别与含义,阅读专题下面的文章了解更多详细内容。

47

2025.09.03

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

521

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

371

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

551

2023.08.03

js是什么意思
js是什么意思

JS是JavaScript的缩写,它是一种广泛应用于网页开发的脚本语言。JavaScript是一种解释性的、基于对象和事件驱动的编程语言,通常用于为网页增加交互性和动态性。它可以在网页上实现复杂的功能和效果,如表单验证、页面元素操作、动画效果、数据交互等。

5602

2023.08.17

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

490

2023.09.01

pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

76

2026.02.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 5.1万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号