MessageChannel 如何实现时间切片

一、MessageChannel 实现时间切片的核心原理(3句话)

  1. 浏览器渲染是每帧 16ms,JS 不能霸占主线程太久,否则卡顿。
  2. MessageChannel 能快速产生一个宏任务 ,比 setTimeout 更快、更稳。
  3. 每执行 5ms 就主动暂停,通过宏任务让出主线程让浏览器渲染,然后再继续。

这就是 时间切片(Time Slicing)


二、我给你封装:终极通用切片方法(直接复制用)

这个方法 接收一个大任务,自动分片,每片5ms,不阻塞页面

javascript 复制代码
/**
 * 基于 MessageChannel 的时间切片工具
 * @param {Function} taskFn 每次执行一小步的函数,return true 表示全部完成
 * @param {Function} onFinish 完成回调
 */
function useTimeSlice(taskFn, onFinish) {
  let isStop = false;
  const channel = new MessageChannel();
  const port1 = channel.port1;
  const port2 = channel.port2;

  function runSlice() {
    if (isStop) return;
    const start = performance.now();

    while (performance.now() - start < 5) {
      const finished = taskFn();
      if (finished) {
        onFinish?.();
        return;
      }
    }

    port1.postMessage(null);
  }

  port2.onmessage = runSlice;
  runSlice();

  // 返回清理方法
  return () => {
    isStop = true;
    port2.onmessage = null;
    port1.close();
    port2.close();
  };
}```

---

三、使用示例(超级简单)

你有一个巨量循环任务,直接用:

javascript 复制代码
let i = 0;
const total = 100000; // 超大任务

// 直接使用!
const stopTask = useTimeSlice(
  // 每一步小任务
  () => {
    console.log("执行:", i);
    i++;
    return i >= total; // 做完返回 true
  },
  // 完成回调
  () => {
    console.log("✅ 全部完成!");
  }
);

// 想停就停
// stopTask()

在 React 里使用:


js 复制代码
useEffect(() => {
  const stop = useTimeSlice(..., ...);
  return stop; // 卸载自动清理
}, []);

四、这个方法到底做了什么?

  • 你的大循环不会一次执行完
  • 每 5ms 自动切一刀
  • 时间到自动暂停,让浏览器去渲染页面
  • 渲染完立刻继续
  • 页面永远不卡顿

这就是 React 内部做时间切片的方式


五、面试标准答案(背会)

MessageChannel 实现时间切片的原理:

  1. 使用 MessageChannel 创建快速宏任务 ,比 setTimeout 更快更稳定。
  2. 通过 performance.now() 计算执行时间。
  3. 每执行 5ms 就主动暂停,让出主线程。
  4. 通过 postMessage 触发下一轮任务,实现可中断、可恢复
  5. 最终达到大任务分片执行,不阻塞渲染的效果。

六、你只要记住一句话

MessageChannel 负责快速调度,5ms 负责控制时间片,
两者结合 = 完美时间切片,就是 React Scheduler 核心。

相关推荐
油丶酸萝卜别吃4 小时前
utils.js 说明文档
开发语言·javascript·ecmascript
zyplayer-doc6 小时前
VuePress类静态文档站和动态知识库怎么选:两种技术路线的适用场景
javascript·人工智能·后端·安全·智能手机
用户938515635078 小时前
从零在浏览器里跑 DeepSeek-R1:WebGPU + Transformers.js 全链路实战(三)
前端·react.js·typescript
To_OC10 小时前
写了 5 个表单 Demo 后,我终于彻底搞懂了 React 受控与非受控组件
前端·react.js·前端框架
码哥DFS11 小时前
构造函数、实例对象、对象原型 ----三者关系
开发语言·javascript·原型模式
满栀58511 小时前
vue动态路由效果
前端·javascript·vue.js·前端框架·vue
jjw_zyfx13 小时前
css vue vite实现闪烁的呼吸效果
javascript·css·vue.js
sunly_13 小时前
React useActionState 的用法详解
前端·javascript·react.js
cyadyx14 小时前
【Three.js】Three.js 中加载 3D 模型
前端·javascript·3d
汉堡大王952714 小时前
前端工程师 TypeScript 上手指南:一条清晰的从入门到精通路线
前端·javascript·react.js