也是用上webworker了

React 16.8,我自己写的的足球应用,问题是模态框没有立即弹出,反而是等了一会才弹出。

scss 复制代码
  useImperativeHandle(ref, () => ({
    showModal: (id: string) => {
      const newState = {
        ...state,
        id,
        teamCount: teamOddList.length,
        tableLoading: true,
        open: true,
      };
      setState(newState);
      setAddedItems(new Map());

      // 初始化已存在的奖金项目
      initializeAddedItems(id);

      getOddResultList(newState, teamOddList);
    },
  }));

我开始以为是 React 响应式设计导致的,因为此时 setState 的是异步的,虽然 showModal 中设置了 open 为 true,后续处理不当,还是会导致 open 隐式设置为 false

仔细检查一番发现没有,并且我已经把 newSate 传递过去了,通过注释代码发现,是getOddResultList导致的,其实在之前的写法中我是加了setTimeout的,只不过时间太久了忘记了为什么加。

如今再写一来觉得setTimeout这种解决方式并不好。而且延迟 20ms 是没用的,看起来像是在等计算完成后再显示模态框。

于是我问了下 Trace,他说是因为getOddResultList有大量的同步计算,建议我用 webworker 来处理。

  • 多重嵌套循环 :对每个球队的赔率信息进行多维度组合计算(胜平负、让球、比分、进球数、半场等)
  • 指数级复杂度 :通过递归函数 getTeamCombinationList 和 againForEach 生成所有可能的投注组合
  • 大量数据处理 :每个组合都需要计算赔率乘积,并进行排序
  • JavaScript 是单线程的,同步计算会完全阻塞主线程
  • 模态框的 open 状态虽然已设置为 true ,但 React 无法进行重新渲染
  • 用户界面会出现"卡顿",模态框无法立即显示

这个函数确实会消耗大量的时间,因为有 4 只球队会产生 9 百万种结果。

使用 webworker 的话,需要将 js 文件放到 public 目录下,通过onmessage来接收消息,通过postMessage来发送消息。

php 复制代码
self.onmessage = function (e) {
  const { teamOddList } = e.data;
  try {
    const result = calculateOddResultList(teamOddList);
    self.postMessage({ success: true, data: result });
  } catch (error) {
    self.postMessage({ success: false, error: error.message });
  }
};

在 jsx 文件中使用 webworker

ini 复制代码
useEffect(() => {
    // 创建 Web Worker

    workerRef.current = new Worker('/oddResultWorker.js');
    workerRef.current.onmessageerror = (e) => {
      console.error('Worker message error:', e);
    };

    // 监听 Worker 消息
    workerRef.current.onmessage = (e) => {
      const { success, data, error } = e.data;
      if (success) {
        allOddResultListRef.current = data;
        setState((preState) => ({
          ...preState,
          total: data.length,
          tableLoading: false,
          oddResultList: data.slice(
            (preState.currentPage - 1) * pageSize,
            preState.currentPage * pageSize
          ),
        }));
      } else {
        console.error('Worker error:', error);
      }
    };

    return () => {
      if (workerRef.current) {
        workerRef.current.terminate();
      }
    };
  }, []);

调用时

typescript 复制代码
    showModal: (id: string, teamOddList: Array<NFootball.ITeamRecordOdds>) => {
      ...
      setAddedItems(new Map());
      initializeAddedItems(id);

      workerRef.current.postMessage({ teamOddList });
    },
相关推荐
AAA阿giao1 天前
从零构建一个现代登录页:深入解析 Tailwind CSS + Vite + Lucide React 的完整技术栈
前端·css·react.js
昨晚我输给了一辆AE861 天前
为什么现在不推荐使用 React.FC 了?
前端·react.js·typescript
不会敲代码11 天前
深入浅出 React 闭包陷阱:从现象到原理
前端·react.js
不会敲代码11 天前
React性能优化:深入理解useMemo和useCallback
前端·javascript·react.js
叶智辽1 天前
【Three.js内存管理】那些你以为释放了,其实还在占着的资源
性能优化·three.js
不会敲代码12 天前
从入门到进阶:手写React自定义Hooks,让你的组件更简洁
前端·react.js
pe7er2 天前
状态提升:前端开发中的状态管理的设计思想
前端·vue.js·react.js
晚风予星2 天前
Ant Design Token Lens 迎来了全面升级!支持在 .tsx 或 .ts 文件中直接使用 Design Token
前端·react.js·visual studio code
青青家的小灰灰2 天前
React 架构进阶:自定义 Hooks 的高级设计模式与最佳实践
前端·react.js·前端框架
BigByte2 天前
我用 6 个 WASM 编码器干掉了 Canvas.toBlob(),图片压缩率直接提升 15%
性能优化·webassembly·图片资源