Skip to content

公开 API 错误模型与重试策略 ​

公开 API 的客户端必须同时判断 HTTP 结果、响应格式和业务字段。一个 HTTP 200 不一定代表业务成功;一个网络超时也不一定代表服务端没有完成写入。

本文只覆盖网页和公开客户端可见的接口行为,不描述服务内部实现。

三层结果 ​

第一层:传输结果 ​

先读取:

  • HTTP 状态码;
  • Content-Type;
  • 响应体是否为空;
  • 请求是否在客户端超时。

文件下载接口可能返回图片或 JSON 错误,不能对所有响应无条件调用 json()。

第二层:通用业务结果 ​

多数 JSON 写入接口使用:

json
{
  "success": true,
  "msg": "success"
}

验证 Token 的接口可能使用:

json
{
  "valid": true,
  "expires_at": "<RFC3339_TIME>",
  "expired": false
}

不要只看 msg 是否为英文成功文字。优先判断布尔字段,再把 msg 用于界面提示。

第三层:数据完整性 ​

业务成功后还要确认数据字段:

  • 列表字段存在且为数组;
  • 分页响应的总数和当前数组可以解释;
  • data 不是意外的 null;
  • 文件接口的内容类型符合预期;
  • 写入后重新读取能看到目标值。

例如恢复缓存返回条数,只表示服务处理的条目数量;它不是所有页面都已经完成索引的证明。

HTTP 状态处理 ​

状态常见含义客户端动作
2xx请求到达服务继续判断业务字段和数据完整性
400参数缺失或格式错误修正本地输入,不自动重试
401Token 无效或已过期停止后台请求,要求重新登录
403账号没有当前权限显示权限提示,不猜测其它入口
404地址或版本不匹配检查基础地址和接口版本
409当前状态不允许写入重新读取状态后再决定
413文件或请求过大缩小范围/文件,确认页面限制
429请求过于频繁使用退避,不并行刷接口
5xx服务暂时异常只对幂等读取有限重试
其它未知传输结果保留状态码和非敏感消息,停止高风险动作

不同部署可能使用不同状态码。表格是客户端分流建议,不是绕过服务规则的依据。

业务失败处理 ​

success: false ​

把 msg 显示给用户并保留当前本地输入。对于写入接口:

  1. 不要立刻换参数重试;
  2. 记录目标字段或索引的脱敏名称;
  3. 重新读取当前状态;
  4. 确认失败是否来自权限、格式、状态或网络;
  5. 只有用户明确确认后再尝试一次。

valid: false ​

立即停止依赖该 Token 的轮询、写入和上传。清理内存中的 Token,保留本地账号显示条目,要求用户重新验证。不要把旧 Token 传给其它端点测试。

成功但数据不完整 ​

如果业务字段缺失、数组类型不对或文件内容为空,按“响应格式异常”处理。不要把不完整响应保存为新的备份,也不要用它覆盖本地有效缓存。

读取请求的退避 ​

只对不改变服务状态的读取操作使用有限重试:

text
第一次失败:等待 1 秒并重试一次
第二次失败:等待 3 秒并重试一次
第三次失败:停止,显示错误和时间

遇到 401、403、400 或明确业务失败时不等待重试;遇到 429 时优先使用服务要求的等待时间。页面离开后取消未完成的读取,避免后台继续消耗会话。

写入请求的幂等边界 ​

以下操作不能因为超时就自动重复:

  • 保存配方;
  • 发布评论或回复;
  • 上传缓存;
  • 删除相片或上传快照;
  • 恢复缓存;
  • 应用订单、重启、挂载或其它机台动作。

超时后的安全顺序是:重新验证 Token → 读取状态/列表 → 对照目标是否已经生效 → 只在确认未生效且用户同意时重试。

文件响应 ​

一个健壮的文件读取器应先检查:

js
const response = await fetch(url, options);
const contentType = response.headers.get('content-type') || '';

if (contentType.includes('application/json')) {
  const result = await response.json();
  // 处理 success/msg
} else if (response.ok) {
  const blob = await response.blob();
  // 交给图片或文件预览器
} else {
  // 记录状态码,不把二进制当 JSON 解析
}

下载文件时还要检查空内容、文件名和浏览器下载权限。不要把文件内容自动上传到错误收集服务。

可观测性字段 ​

客户端日志只保留排障所需的最小字段:

text
时间(含时区)
接口分类和动作
HTTP 状态
业务 success/valid
响应耗时
是否发生重试
脱敏后的账号别名

不要记录请求体原文、完整 URL 查询值、Token、密码、访问码、二维码、机台标识、完整 JSON 或图片内容。若必须关联请求,使用客户端生成的随机追踪编号,不要使用凭据本身。

开发环境模拟 ​

开发者可以在本地把以下结果作为测试夹具:

  1. 200 + success: true;
  2. 200 + success: false;
  3. 401 + valid: false;
  4. 429 + 退避提示;
  5. 503 + HTML 错误页;
  6. 200 + 图片二进制;
  7. 200 + JSON 错误;
  8. 客户端超时但下一次读取已显示写入成功。

测试夹具中的 Token 和地址必须是占位符。不要用真实聊天记录、真实备份或生产凭据做错误处理测试。

Released under the CC BY-NC-SA 4.0 License.