随机图片 API 接入:先确定接口约定、缓存与去重,再谈体验
随机图片接口的难点在随机性带来的缓存、去重、体积与合规四个变量,而不只是取回一张图片。本文依次说明请求前需固定的四项接口约定(响应形态、随机语义、缓存指令、限额与失败形态)、二进制响应与错误响应必须分开处理、三种可选缓存策略与环形缓冲去重、按展示位取尺寸、以占位端点演示的未执行示例代码,以及版权授权方面需要以接口方条款为准的部分。文中不含具体端点、参数名、配额与授权结论,这些需按官方文档核实。
随机图片 API 的接入难点不在“取一张图”,而在随机性同时引入了四个变量:缓存、去重、体积和合规。本次没有可用的接口文档或正文材料,因此下面不涉及具体端点、参数名、调用配额和图片版权条款——这些需以接口方官方文档为准,本文标注为待核实。能确定的是工程侧的处理顺序:先固定接口约定,再决定缓存策略,最后才做体验优化。
请求前要固定的四项接口约定#
- 响应形态:是直接返回图片二进制,还是返回含图片 URL 的 JSON。前者少一次请求;后者便于切换尺寸、加水印或做多图源,但多一跳。
- 随机语义:每次请求是否保证不同、能否按标签或尺寸筛选、是否支持 seed。文档未说明前,按“不保证不重复”设计。
- 缓存指令:
Cache-Control、ETag、Vary的实际取值。随机图片若被中间层缓存,用户会反复看到同一张。 - 限额与失败形态:超限时返回 429 还是 403,响应体是 JSON 还是 HTML 错误页。后者会让客户端难以区分“密钥错”和“额度耗尽”。
图片和错误必须分开判断#
图片类接口的常见问题是错误也以 200 返回:一张占位图、一段 HTML 错误页,或者空响应体。客户端只检查 response.ok,就会把错误页当壁纸存进缓存。建议的判断顺序是:先看 Content-Type 是否为 image/*,再设一个字节数下限挡住空包,任一不满足按错误处理,并且不写入任何缓存。
缓存策略与去重#
“随机”和“缓存”天然冲突,通常在三者间取舍:
- 不缓存:请求时带
cache: "no-store",实现最简单,代价是延迟和流量全部由源站承担。 - 短时缓存加手动换图:适合壁纸场景,用户点“换一张”才发新请求,其余时间读本地。
- 预取队列:本地常备 N 张(例如 5 张),展示一张、后台补一张,把网络延迟安排在用户不察觉的时候。
去重同样是必需步骤:维护最近 K 个图片标识(URL 或内容哈希)的环形缓冲,命中就丢弃并重取,最多重试一次。图片池很小时,没有这个上限的重试会变成死循环。
占位示例(未执行)#
以下代码用于说明判断顺序,端点、认证方式和字段均为占位,未经实际运行;请按官方文档替换,不要照抄请求真实服务。
// 未执行示例:ENDPOINT 与鉴权头均为占位
const ENDPOINT = "https://api.example.com/random"; // 占位
const seen = new Set();
async function fetchWallpaper(signal) {
const res = await fetch(ENDPOINT, {
signal,
cache: "no-store",
headers: { Authorization: "Bearer YOUR_KEY" }, // 占位密钥
});
const type = res.headers.get("content-type") || "";
if (!res.ok || !type.startsWith("image/")) {
throw new Error(`bad response: ${res.status} ${type}`); // 不缓存错误
}
const blob = await res.blob();
if (blob.size < 1024) throw new Error("suspiciously small body");
const id = res.headers.get("etag") || `${blob.size}:${type}`;
if (seen.has(id)) return null; // 由调用方决定是否重试一次
seen.add(id);
return blob;
}
体积、尺寸与合规边界#
按展示位请求对应宽度,不要先拿原图再缩:桌面壁纸和缩略图卡片共用同一个请求,会把带宽浪费在用户看不到的像素上。是否支持尺寸参数、支持哪些值,待核实。
壁纸类内容牵涉版权与授权:能否商用、是否要求署名、是否允许热链,都必须以接口方条款为准,本文无法确认。工程上可先做到三点:不把图片转存为自有资源对外分发;保留来源标识字段;为下架留一条删除通道。
发布前的验收项#
| 检查项 | 判定方式 | 拿不到结论时 |
|---|---|---|
| 重复率 | 连续请求若干次,统计唯一标识占比(样本量和判定标准需自行记录) | 按不重复处理,客户端去重 |
| 错误形态 | 用错误密钥和超限请求各试一次,看状态码与响应体 | 同时校验状态码、Content-Type 与字节数 |
| 缓存头 | 查看 Cache-Control、ETag 是否存在 | 客户端强制 no-store |
| 授权条款 | 阅读接口方服务条款原文 | 视为不可商用,先不进入生产 |
把这张表填完,再谈预加载、转场动画和画质分档;顺序反了,优化只是在放大一个尚未确定的接口约定。