worklog

2026-03-09 工作日志:美伊看板数据加载容错机制 + Bug 修复

今天的核心工作是解决美伊战争局势看板(warpannel.sophia.beer)首次打开时经常白屏、需要手动点刷新才显示数据的问题。


一、问题诊断

现象:用户打开看板后,页面有时完全没有数据,需要手动点击”刷新数据”按钮才能正常显示。

根因分析

  1. Vercel 冷启动:SQLite 缓存存在 /tmp(临时目录),冷启动时数据库为空,/api/latest 返回 {expired: true},触发 refreshData() 全量拉取
  2. Promise.all 脆弱性refreshData()Promise.all 同时请求 7 个接口(5 个 batch + polymarket + EC),冷启动时 serverless 函数初始化慢,任何一个请求超时或失败,整个 Promise.all 就报错,页面白屏
  3. 无重试机制:失败后只弹一个 toast 提示,不会自动重试
  4. 手动点击能成功:因为第一次请求已经让 serverless 函数热了,第二次自然快

二、容错与重试机制

safeFetch 封装

新增 safeFetch(url, timeoutMs) 函数:

Promise.allSettled + 按需重试

Promise.all 替换为 Promise.allSettled,并增加三层重试逻辑:

7 个请求同时发出
      ↓
  检查哪些失败了
      ↓
┌──────────────────────────────────────┐
│ 全部成功    → 直接渲染               │
│ 部分失败    → 等 2s,只重试失败的请求 │
│ 全部失败    → 等 3s,全部重试一遍     │
└──────────────────────────────────────┘
      ↓
  合并数据,渲染页面

分析接口独立容错

/api/analyze 失败不再阻断指标渲染——即使分析面板为空,指标卡片和 Polymarket 数据仍正常展示。


三、Bug 修复(代码审查发现)

对全部代码做了一次完整审查,发现并修复了 4 个问题:

问题 严重度 修复
ec.price 应为 ec.value 严重 — 后端返回 value 字段,前端检查的是 price,导致 EC 期货数据有时不渲染 改为 ec.value !== undefined
cacheAge 未做类型转换 中 — HTTP header 返回字符串,直接做算术运算有隐患 加了 parseInt()
it.slug 未做空值检查 中 — Polymarket 渲染时若 slug 不存在会 TypeError 加了 && 空值守卫
backend/requirements.txtakshare 低 — 本地开发环境安装依赖会遗漏 补上了

四、文档更新

更新 DESIGN.md,补充”容错与重试机制”章节,说明 safeFetch、Promise.allSettled、按需重试的设计。


五、今日提交记录

提交 说明
858096a feat: 添加单个请求失败自动重试 + safeFetch 容错机制
e6b57da fix: EC 字段名修正、cacheAge 类型转换、slug 空值守卫、akshare 依赖补全
d71b663 docs: DESIGN.md 补充容错与重试机制文档