跳转至

[ISSUE-0029] DataView 性能浪费 + listener 无清理

发现者:v0.10.45 第二轮独立 audit agent(验证 anchor bias 是否消除时) 相关源码src/sections/data/data-view.tsx:117-135src/sections/page/local-data-view.tsx:434-461

Bug E:浪费 IndexedDB taskId 索引(中-高,性能)

现状(v0.10.45 之前)

// 每 5s 轮询
const query: any = {
  limit: isFiltered ? FILTER_CAP : CAP,  // 50000
  order: { by: 'id', type: 'desc' },
};
const list = await selectByQuery('MapTaskData', query);
if (isFiltered) return list.filter((r) => r.taskId === filterTaskId);

taskId 列在 base.ts 已配 enableSearch: true 索引,但没用 where: { taskId }。 每 5s 拉全表 50000 行到内存再 JS filter。

影响

场景 IO 量 浪费
DB 20k 行,单 task 100 行 拉 20k → 留 100 200× 无效 IO,每 5s 一次
DB 50k 行,单 task 1k 行 拉 50k → 留 1k 50× 无效 IO,大对象 GC 压力

用户商家数越多,问题越严重。

修复

const query: any = isFiltered
  ? { where: { taskId: filterTaskId }, limit: FILTER_CAP, order: { by: 'id', type: 'desc' } }
  : { limit: CAP, order: { by: 'id', type: 'desc' } };
return (await selectByQuery('MapTaskData', query)) || [];

走 IndexedDB taskId 索引,只拉真正需要的行

Bug S4:onMessage listener 无 cleanup(中,React lifecycle)

现状

const lisenter = () => {
  onMessage('has-new-data', async ({ data }: any) => {  // 注册
    // ... 用 setState / countRun
  });
};

useEffect(() => {
  lisenter();
}, []);  // ❌ 无 cleanup return

onMessage 注册的 callback 在组件 unmount 后仍然活着。webext-bridge 是单 handler 覆盖 模型所以不会累积,但 stale closure 持有已卸 component scope —— 新数据触发时跑的是旧 instance 的 setState / countRun,React 报 "set state on unmounted component" warning。

修复

const lisenter = () => {
  return onMessage('has-new-data', async ({ data }: any) => { ... });
  //     ^ 返回 off 函数
};

useEffect(() => {
  const off = lisenter();
  return () => off?.();  // ✅ unmount 时清理
}, []);

为什么前一轮独立 agent 没发现?

第一轮 agent 关注 background SW / 调度 / 状态机层。这次第二轮我明确告诉它"前端 React lifecycle 是审查盲区",它才找到。

改动文件

文件 改了什么
src/sections/data/data-view.tsx Bug E: 用 where 走索引
src/sections/page/local-data-view.tsx Bug S4: lisenter 返 off + useEffect cleanup
package.json 0.10.44 → 0.10.45

验证

  • pnpm compile 0 错
  • pnpm build 8.16s
  • 📋 浏览器实测路径:
  • Bug E: 多商家场景下「按任务筛选」切换应明显更流畅
  • Bug S4: 频繁切 tab unmount/remount 商家列表,React DevTools 不应有 "memory leak" warning

如何避免再犯

  • 任何 useEffect 内注册的 listener / observer / subscription 必须返回 cleanup
  • IndexedDB 查询有 enableSearch 的列必须用 where 走索引 —— 否则全表扫
  • 轮询查询 5s 一次很容易放大问题 —— 每次 IO 量 × 12 次/分

系统性发现(登记到 raw/inbox)

第二轮 agent 还指出:"本会话 14 个 issue 0 个针对 React lifecycle" —— 这是真盲区。已登记 docs/raw/inbox/2026-05-26-frontend-lifecycle-audit-blindspot.md

相关

  • [[0028-captcha-resume-missing-map-schedule|0028-拦截恢复漏调地图调度]] — 同样由独立 agent 发现
  • 独立agent审查 — 流程沉淀