返回文章列表

Chrome 插件的任务队列与重试机制

页面自动化最容易坏在状态不可控:页面没加载完、按钮找不到、网络请求失败、用户切换标签页。 任务队列的价值是把这些不确定性收敛成可恢复的状态机。

任务必须是可描述的对象

不要把自动化逻辑写成一串连续点击。每个任务应该有 id、type、payload、status、attempts、createdAt 和 lastError。 这样你才能暂停、恢复、去重、排序和排查失败原因。

{
  "id": "task_20260519_001",
  "type": "SEND_REPLY",
  "payload": {"threadId": "abc", "templateId": "price"},
  "status": "queued",
  "attempts": 0,
  "lastError": null
}

用状态机约束流程

常见状态包括 queued、running、waiting_page、retrying、done、failed、paused。插件的 popup 只负责展示和操作状态, 真正执行逻辑放在 background 或 content script 协作完成。状态变化要写日志,避免出现“插件没反应”却不知道卡在哪一步。

关键原则:任务执行器每次只做一个小动作,然后把结果写回队列。不要在一个函数里做完整流程。

重试不是简单 setTimeout

重试要区分错误类型。页面元素不存在可能需要等待 DOM;接口 429 需要退避;账号状态异常应该立即暂停;业务校验失败则不应重试。 对可重试错误使用指数退避,并设置最大次数,防止插件在后台无限循环。

  • transient:网络抖动、页面加载慢,可重试。
  • rate_limit:频率限制,延迟更久并降低并发。
  • validation:输入不合法,不重试,直接失败。
  • account_risk:账号或页面状态异常,暂停队列等待人工处理。

IndexedDB 比 localStorage 更适合队列

队列需要存结构化对象、查询状态、按时间排序和写入日志,IndexedDB 更稳。localStorage 适合少量配置,不适合高频任务状态。 如果任务涉及敏感内容,存储层还要做字段裁剪和过期清理,只保存执行所需的最小数据。

队列是否支持暂停、恢复和清空。
任务是否有唯一 id 和幂等处理。
失败是否保存可读错误,而不是只写 console。
执行速率是否可配置,避免对页面和账号造成压力。