fetch:请求数据
这是什么:fetch = 浏览器内置的请求函数,fetch(地址) 发出一个 HTTP 请求,返回一个 Promise(「取餐号」),数据回来后用 .then 领取。
为什么用:它是现代浏览器统一的标准写法——不用装任何库、不用 new 任何对象,一行代码把服务器数据拿回来,是 AJAX 时代的主力工具。
如何用:本章用免费公共测试接口 JSONPlaceholder 实战,先请求一篇文章的 JSON 并打印。
第一发:请求一篇文章
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then(function (res) {
return res.json() // 第一段:拿到「响应」,拆出 JSON
})
.then(function (data) {
console.log(data) // 第二段:拿到真正的数据对象
})
你会看到(控制台里一个对象,点开看):
{userId: 1, id: 1, title: 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit', body: 'quia et suscipit\nsuscipit…'}
拆解这两段:
| 阶段 | 拿到什么 | 说明 |
|---|---|---|
第一段 .then(res => …) |
响应对象 res |
只有状态码、响应头等「快递外壳」,还没有数据内容 |
第二段 .then(data => …) |
解析后的 JSON 对象 | res.json() 把外壳里的正文读出来并解析 |
为什么中间要夹一个 res.json()
新手最懵的点来了:res 里拿到的不是数据本身,而是「响应」。正文可能是 JSON、也可能是纯文本、图片,浏览器不知道你要哪种,所以要你明确说一句「按 JSON 拆包」——这就是 res.json()。
更绕的是:读正文也要时间(数据可能很大),所以 res.json() 返回的又是一个 Promise,得再 .then 一次。两段式由此而来:
fetch(地址) → Promise ①(响应到了)
res.json() → Promise ②(正文读完、解析好了)
第二个 .then(data) → 终于拿到数据对象
想要纯文本就用
res.text(),两者都会返回新的 Promise。
res.ok:状态码要自己查
第 1 章说过:404、500 不算 fetch 的失败。只有 res.ok 为 false 时主动抛错,才走得到 catch:
fetch('https://jsonplaceholder.typicode.com/posts/99999') // 不存在的文章
.then(function (res) {
if (!res.ok) { // ok 为 false = 404 等
throw new Error('HTTP ' + res.status)
}
return res.json()
})
.then(function (data) {
console.log('拿到数据:', data)
})
.catch(function (err) {
console.error('请求出错了:', err.message) // HTTP 404
})
你会看到:
请求出错了: HTTP 404
.catch 能接住两类错误:① 网络断掉 / 域名写错(fetch 自动 reject);② 你自己 throw 出来的状态码错误。标准模板 = ok 自查 + catch 兜底,往后每章都用它。
GET 请求带参数:拼在地址上
查询类参数(分页、搜索词)直接拼在 URL 后面,? 开头、& 分隔:
// 请求第 1 页、每页 2 篇的文章列表
fetch('https://jsonplaceholder.typicode.com/posts?_page=1&_limit=2')
.then(res => res.json())
.then(list => console.log(list.length)) // 2(数组里 2 篇文章)
这种「取数据、不改服务器」的请求用的是 GET 方法,fetch 不写 method 时默认就是它。
记忆口诀:fetch 发出去,then 分两段;json 拆外壳,ok 自己看。
📝 本章小结
fetch(url)发 GET 请求,返回 Promise;两段 then:先拿响应,再res.json()拿数据res.json()/res.text()返回的也是 Promise,所以要 then 两次- 404、500 不会让 fetch 报错,要
if (!res.ok) throw new Error(...)主动抛给.catch - GET 参数拼在 URL 上:
?a=1&b=2
动手改
- 把请求地址改成
/users/1,打印这个用户的名字(提示:字段叫name) - 请求
/posts?_limit=5,打印返回数组的长度 - 故意把域名改成
https://不存在的域名.xyz,看.catch接到什么错