应先判断响应是否为空再解析:对204/205/304状态码直接返回null;否则用text()获取后校验内容,再尝试json解析,避免syntaxerror或body stream locked错误。

当 Fetch API 返回的响应内容为空(比如状态码是 204 No Content、205 Reset Content,或服务器返回空字符串/空 JSON),直接调用 response.json() 或 response.text() 会报错或得到意外结果。关键是要先判断响应体是否可读、是否有内容,再选择合适的解析方式。
检查响应状态和 headers 判断是否可能为空
HTTP 状态码 204、205、304 本身规定响应体必须为空;部分 2xx 成功响应也可能返回空体。可通过 response.status 和 response.headers.get('content-length') 快速预判:
- 若
response.status === 204 || response.status === 205,直接跳过解析,视为“成功但无数据” - 若
response.headers.get('content-length') === '0',大概率无响应体,避免调用.json()或.text() - 注意:
content-length可能不存在(如分块传输),所以不能只依赖它
用 response.bodyUsed 和 response.ok 配合容错处理
response.ok 表示状态码在 200–299 范围,但不保证有响应体;response.bodyUsed 可判断流是否已被读取(防止重复读取)。推荐结构:
- 先检查
!response.ok,统一处理错误(如 throw new Error) - 再根据状态码或业务逻辑决定是否需要读取:例如
response.status === 200才尝试.json(),否则直接return null或{} - 避免对已读响应再次调用
.json()—— 会抛TypeError: Failed to execute 'json' on 'Response': body stream is locked
安全读取响应体的通用写法
最稳妥的方式是统一用 response.clone() 分支处理,或用 async/await + try/catch 包裹解析操作:
- 对可能为空的接口,优先用
response.text()获取原始字符串,再手动判断是否为空白:if (!bodyText.trim()) return {}; - 若预期为 JSON,可包裹
try { return await response.json(); } catch { return {}; }—— 因为空响应调用.json()会触发 SyntaxError - 也可用
response.arrayBuffer()检查字节长度:const buf = await response.arrayBuffer(); if (buf.byteLength === 0) return null;
封装一个健壮的 fetch 工具函数
把上述逻辑收拢成可复用函数,减少重复判断:
async function safeFetch(url, options = {}) {
const res = await fetch(url, options);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
// 明确跳过空响应体
if ([204, 205, 304].includes(res.status)) return null;
try {
const text = await res.text();
return text.trim() === '' ? {} : JSON.parse(text);
} catch (e) {
// 非 JSON 响应(如纯文本、HTML)可按需 fallback
return { raw: text };
}
}
这样调用时无需每次都写防御逻辑:const data = await safeFetch('/api/user');
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











