主题
Request 与 Response
在 fetch 体系里,请求和响应不是单纯的文本结果,而是两个正式对象:
RequestResponse
理解它们之后,很多 fetch、缓存、Service Worker、流式读取相关代码会更容易看懂。
Request 是什么
Request 表示一次请求本身,里面会带着:
- URL
- method
- headers
- body
- mode
- credentials
- cache
- redirect
js
const request = new Request('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ page: 1 }),
})它可以直接传给 fetch:
js
const response = await fetch(request)Response 是什么
Response 表示一次响应对象。
js
const response = await fetch('/api/users')
console.log(response.status)
console.log(response.ok)
console.log(response.headers.get('content-type'))它不只是“响应体内容”,还包含状态码、响应头、是否重定向等信息。
常用属性先记住哪些
Request
最常见的是:
request.urlrequest.methodrequest.headers
js
const request = new Request('/api/users', {
method: 'POST',
body: JSON.stringify({ name: 'Tom' }),
})
console.log(request.method)
console.log(request.url)Response
最常见的是:
response.okresponse.statusresponse.statusTextresponse.headersresponse.url
js
const response = await fetch('/api/users')
console.log(response.ok)
console.log(response.status)
console.log(response.statusText)
console.log(response.url)其中:
ok一般表示是否是2xxstatus是 HTTP 状态码
读取响应体
最常见的还是从 Response 里取数据:
js
const response = await fetch('/api/users')
const data = await response.json()常见读取方法包括:
json()text()blob()arrayBuffer()formData()
请求体和响应体为什么常说“只能读一次”
因为底层 body 通常是流,一旦消费过,就不能再按原样重复读。
js
const response = await fetch('/api/users')
await response.json()
// await response.text() // 再读通常就不行了这也是 fetch 体系里很容易踩的坑。
为什么有时需要 clone()
如果同一个响应既想给页面用,又想额外做缓存或日志,就需要复制一份。
js
const response = await fetch('/api/users')
const copy = response.clone()
const data = await response.json()
const text = await copy.text()这在 Service Worker 里尤其常见。
也可以手动创建 Request
js
const request = new Request('https://api.example.com/users', {
method: 'GET',
headers: {
Accept: 'application/json',
},
})这适合:
- 提前封装请求对象
- 在拦截链里传递请求
也可以手动创建 Response
js
const response = new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: {
'Content-Type': 'application/json',
},
})这在模拟响应、缓存代理、Service Worker 返回自定义结果时很常见。
Headers
Headers 是专门处理请求头和响应头的对象接口。
js
const headers = new Headers()
headers.set('Content-Type', 'application/json')
headers.set('Authorization', 'Bearer token')也可以从响应里读:
js
const response = await fetch('/api/users')
console.log(response.headers.get('content-type'))和 XHR 的区别
相比 XMLHttpRequest,fetch 体系更偏:
- 对象化
- 流式化
- 可组合
所以 Request / Response / Headers 更适合做中间层封装,而不只是简单发请求。
使用建议
- 把
Request理解成“请求对象”,把Response理解成“响应对象”。 - 读取 body 前先想清楚是否后面还要复用。
- 需要重复消费时,用
clone()。 - 看到 Service Worker、缓存代理、流式读取时,优先联想到
Request和Response模型。
