当前位置: 首页 > article >正文

前端笔记——大数据量浏览器卡顿优化思路

多任务数据量处理卡顿问题

任务分批次

为避免阻塞,可以将 长时间的单一任务 拆分成多个小任务并分批执行。这样可以在两次任务之间让浏览器有时间处理渲染、用户输入等操作。两种常见方法:

  1. setTimeout 方法
    • 使用 setTimeout 将任务分段,每段任务执行完毕后,通过定时器在稍后执行下一段。
    • 例如:计算一个大型数组的和时,将数组分块,每次计算一部分,延迟剩余部分。
  2. requestAnimationFrame 方法
    • 更适合与页面绘制相关的任务。
    • 它会在每次浏览器刷新帧(通常是 16.67 毫秒,60 FPS)时调用指定的回调函数。
    • 确保在每次任务之间,浏览器有机会完成页面渲染。

例子

// 用 setTimeout 拆分长任务
function performTaskInChunks(task, chunkSize) {
  let index = 0;
  function processChunk() {
    const end = Math.min(index + chunkSize, task.length);
    for (; index < end; index++) {
      // 执行任务的每一小部分
      console.log(`Processing: ${task[index]}`);
    }
    if (index < task.length) {
      setTimeout(processChunk, 0); // 等待主线程空闲后继续
    }
  }
  processChunk();
}

// 用 requestAnimationFrame 分布任务
function performTaskWithRAF(task) {
  let index = 0;
  function processFrame() {
    if (index < task.length) {
      console.log(`Processing: ${task[index]}`);
      index++;
      requestAnimationFrame(processFrame); // 下一帧继续任务
    }
  }
  processFrame();
}

// 示例数据
const largeTask = Array.from({ length: 1000 }, (_, i) => i);
performTaskInChunks(largeTask, 50);  // 用 setTimeout 分块执行
performTaskWithRAF(largeTask);       // 用 requestAnimationFrame 分块执行

Web Workers后台执行

Web Workers 是解决大数据量运算导致页面卡顿问题的强大工具。通过将计算任务移到后台线程,主线程可以专注于 UI 渲染和用户交互,显著提升页面的流畅度和用户体验。

Web Workers 的优势
  1. 多线程支持
    • JavaScript 主线程与 Web Worker 是两个独立的线程。
    • 主线程主要负责页面的 UI 渲染与事件处理,而 Web Worker 执行后台计算任务。
  2. 无阻塞主线程
    • Web Workers 的计算任务不会阻塞主线程,页面可以继续响应用户操作。
  3. 与主线程通信
    • 主线程和 Web Worker 通过消息传递的方式通信,使用 postMessageonmessage
  4. 安全隔离
    • Worker 线程运行在独立的作用域中,没有直接访问 DOM 或主线程变量的能力。
例子
  1. 创建一个 Worker 脚本文件

    • Worker 的代码需要放在一个单独的文件中。

    • 示例:worker.js

      // worker.js
      self.onmessage = function (e) {
      console.log(‘Worker received data:’, e.data);
      const result = heavyComputation(e.data);
      self.postMessage(result);
      };

      function heavyComputation(data) {
      // 模拟耗时计算
      let sum = 0;
      for (let i = 0; i < data.length; i++) {
      sum += data[i];
      }
      return sum;
      }

  2. 主线程与 Worker 通信

    • 在主线程中加载 Worker 文件并与其交互。

      // main.js
      const worker = new Worker(‘worker.js’);

      // 发送数据到 Worker
      worker.postMessage([1, 2, 3, 4, 5]);

      // 接收 Worker 的处理结果
      worker.onmessage = function (e) {
      console.log(‘Result from worker:’, e.data);
      };

      // 处理 Worker 的错误
      worker.onerror = function (error) {
      console.error(‘Worker error:’, error.message);
      };

  3. Worker 的终止

    • 如果 Worker 不再需要,可以终止它以释放资源。

      javascript

      复制代码
      worker.terminate();


Web Workers 的类型
  1. Dedicated Workers(专用 Worker)
    • 最常用的 Worker 类型。
    • 一个 Worker 仅供一个主线程使用。
  2. Shared Workers(共享 Worker)
    • 可被多个主线程共享。
    • 不同页面的同源脚本可以共享同一个 Worker。
  3. Service Workers
    • 主要用于控制网络请求和缓存,常见于 PWA 应用。
    • 不直接用于数据计算。

Web Workers 的局限性
  1. 无法访问 DOM
    • Worker 线程不能直接操作页面的 DOM。
    • 需要通过消息传递将结果交回主线程,由主线程更新 UI。
  2. 通信开销
    • 主线程和 Worker 之间的通信需要序列化和反序列化,处理复杂数据时可能会增加延迟。
  3. 浏览器支持
    • 大多数现代浏览器支持 Web Workers,但较老版本浏览器可能不支持。
  4. 额外的资源开销
    • Worker 是独立线程,占用额外的内存和计算资源。

优化示例:使用 Web Worker 处理大数据计算

以下是一个计算大数据数组总和的例子:

// worker.js
self.onmessage = function (e) {
    const data = e.data;
    let sum = 0;
    for (let i = 0; i < data.length; i++) {
        sum += data[i];
    }
    self.postMessage(sum);
};

// main.js
const worker = new Worker('worker.js');
const largeData = Array.from({ length: 1e7 }, (_, i) => i); // 大量数据

console.log('Sending data to worker...');
worker.postMessage(largeData);

worker.onmessage = function (e) {
    console.log('Result from worker:', e.data); // 显示总和
};

worker.onerror = function (error) {
    console.error('Worker error:', error);
};

利用空闲时间执行

requestIdleCallback 是一种浏览器 API,它允许开发者在浏览器的空闲时间执行非紧急的后台任务,而不会影响关键的渲染和用户交互操作。

这个 API 的主要目的是提高页面的流畅度和响应性,尤其是在需要执行较轻量的后台任务时,比如日志记录、数据预加载等。

优势

利用浏览器空闲时间

  • 只有在浏览器完成关键任务(如页面布局、渲染和事件处理)并且有空闲时间时,才会调用 requestIdleCallback 提供的回调函数。

带有超时机制

  • 如果任务不能在空闲时间内执行(如因为任务队列繁忙),可以通过超时设置确保任务最终被执行。

低优先级任务的好帮手

  • 专为非紧急任务设计,比如分析用户行为、缓存数据、预取资源等。
例子
// 定义任务队列
const tasks = Array.from({ length: 1000 }, (_, i) => () => console.log(`Task ${i}`));

// 使用 requestIdleCallback 处理任务
function processTasks(deadline) {
    while (deadline.timeRemaining() > 0 && tasks.length > 0) {
        const task = tasks.shift(); // 从队列中取出任务
        task(); // 执行任务
    }

    // 如果还有剩余任务,继续请求空闲回调
    if (tasks.length > 0) {
        requestIdleCallback(processTasks);
    }
}

// 开始处理任务
requestIdleCallback(processTasks);

http://www.kler.cn/a/446268.html

相关文章:

  • 开源轮子 - Logback 和 Slf4j
  • 通过阿里云 Milvus 与 PAI 搭建高效的检索增强对话系统
  • CLION中运行远程的GUI程序
  • 部署开源大模型的硬件配置全面指南
  • 现代控制理论——自由度
  • 系统思考—战略共识
  • 青少年编程与数学 02-004 Go语言Web编程 06课题、RESTful API
  • ChatGPT与接口测试工具的协作
  • 鸿蒙项目云捐助第十六讲云捐助使用云数据库实现登录注册
  • GaussDB 企业版轻量化部署探索
  • AIGC与现代教育技术
  • C语言-左移、右移
  • 《国产单片机,soc的一些现实问题》
  • 光谱相机在农业的应用
  • onlyoffice连接器 二次开发 合同等制式模板化技术开发方案【三】
  • 嵌入式软件C语言面试常见问题及答案解析(二)
  • 视频点播系统|Java|SSM|VUE| 前后端分离
  • ollama部署本地大模型,Linux以及python调用
  • Mac配置 Node镜像源的时候报错解决办法
  • Mybatis使用xml及纯注解实现增删改查操作
  • 【Verilog】实验八 有限状态机设计
  • vue2实现word在线预览
  • Linux shell脚本用于常见图片png、jpg、jpeg、webp、tiff格式批量添加文本水印
  • 负载均衡+LNMP+rsync+NFS+lsync部署流程
  • QT exe文件设置图标【终极解决方案!】
  • word实现两栏格式公式居中,编号右对齐