在进行接口请求时,为了减少重复代码的书写可以对fetch进行二次封装,要用的时候直接调就行了。
js
async function http({method, url, params, data, headers = {}}) {
// GET请求参数处理
if (params) {
url += '?' + new URLSearchParams(params).toString();
}
const options = {
method,
headers,
credentials: 'include', // 包含跨域凭据
...(data && {body: JSON.stringify(data)}) // 如果有data就添加body
};
const res = await fetch(url, options);
// 错误处理
if (!res.ok) {
const errorData = await res.json().catch(() => ({}));
throw new Error(`HTTP error! status: ${res.status}, message: ${errorData.message || '未知错误'}`);
}
// 特殊处理SSE响应
if (res.headers.get('Content-Type')?.includes('text/event-stream')) {
return res;
}
// 默认返回JSON
return res.json();
}
二次封装详解
这段代码 ...(data && {body: JSON.stringify(data)})
使用了几个JavaScript的高级特性,我来详细解释它的工作原理:
1. 逻辑与运算符(&&)的短路特性
data && {body: JSON.stringify(data)}
使用了逻辑与运算符的短路特性:
- 如果
data
是假值(如null
、undefined
、false
、0
、""
等),整个表达式会返回data
的值,且不会计算右边的表达式 - 如果
data
是真值,则返回右边的对象{body: JSON.stringify(data)}
2. 对象展开运算符(...)
...
是对象展开运算符,它会将对象的可枚举属性展开到新的对象中:
- 如果
data
存在,data && {body: JSON.stringify(data)}
会返回一个对象,然后被展开到options
对象中 - 如果
data
不存在,表达式返回data
(假值),展开一个假值不会有任何效果
特殊处理SSE响应
js
if (res.headers.get('Content-Type')?.includes('text/event-stream')) {
return res; // 直接返回原始响应对象,保留原始响应:让调用方自己处理流式数据(如通过 `EventSource` 或手动读取流)
}
1. 什么是SSE(Server-Sent Events)? SSE 是一种服务器向客户端单向实时推送数据的技术,特点是:
- 基于HTTP协议,使用简单的文本格式(
text/event-stream
) - 服务器可以持续发送多条消息(如聊天消息、实时日志、股票价格更新)
- 客户端通过
EventSource
API 或直接处理原始响应流来监听消息
2. 为什么需要特殊处理SSE响应?
普通HTTP请求 vs SSE请求的区别
特性 | 普通HTTP请求 | SSE请求 |
---|---|---|
响应类型 | application/json等 | text/event-stream |
数据格式 | 一次性完整响应 | 持续流式文本(多条消息) |
客户端处理方式 | 直接解析JSON | 监听事件流 |
连接特性 | 请求-响应后立即关闭 | 长连接,服务器可持续推送 |