# 两小时入门 fetch
fetch 基本认知
以前请求方式
那么目前除了使用 XMLHttpRequest
发送请求之外,还有没有其他方式呢?
什么是 fetch
Fetch
被称之为下一代 Ajax
技术,内部采用 Promise
方式来处理数据
可以直接.then 即可
API 语法简洁明了,比 XMLHttpRequest
更加简单易用
采用了模块化设计,API 分散于多个对象中(如:Response 对象、Request 对象、Header 对象)
通过数据流( Stream 对象)处理数据,可以分块读取,有利于提高网站性能,对于大文件或者网速慢的场景极为有用
兼容性:浏览器支持程度如何?
- 最新统计(下图所示):fetch 可以支持到
96.83%
的用户端,除了 IE,主流浏览器都已兼容
- 注意点:不兼容 IE

fetch 如何使用
fetch 发送基本 get 请求
介绍:
- 如果 fetch() 只接收了一个 url 字符串 参数,表示默认向该网址发送 get 请求,会返回一个 Promise 对象
- 如果需要设置 get 的参数,直接拼接到 url 地址上即可
语法:
1 2 3
| fetch(url) .then(...) .catch(...)
|
fetch 发送基本的 get 请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
fetch('http://ajax-base-api-t.itheima.net/api/getbooks') .then((res) => { return res.json() }) .then((json) => { console.log(json) }) .catch((err) => { console.log(err) })
|
使用 async-await 改写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
async function getData() { try { let res = await fetch('http://ajax-base-api-t.itheima.net/api/getbooks') let json = await res.json() console.log(json) } catch (err) { console.log(err) } } getData()
|
添加查询参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
async function getData1() { try { let res = await fetch('http://ajax-base-api-t.itheima.net/api/getbooks?id=1') console.log(res) let json = await res.json() console.log(json) } catch (err) { console.log(err) } } getData1()
|
Response 对象
fetch 请求成功以后,得到的是一个 Response 对象。它是对应服务器的 HTTP 响应。
1 2 3 4 5 6 7 8 9
| async function getData() { const res = await fetch('http://ajax-base-api-t.itheima.net/api/getbooks') console.log(res) console.log(res.ok) console.log(res.status) console.log(res.statusText) console.log(res.url) } getData()
|
常见属性
属性 |
含义 |
res.ok |
返回一个布尔类型,表示请求是否成功 |
res.status |
返回一个数字,表示 HTTP 回应的状态码(例如:200,表示以请求成功) |
res.statusText |
返回状态的文本信息(例如:请求成功之后,服务器返回 ok) |
res.url |
返回请求的 url 地址 |

常见方法
Response 对象根据服务器返回的不同类型的数据,提供了不同的读取方法。
其中最常用的就是 res.json()
方法 |
含义 |
res.json() |
得到 JSON 对象 |
res.text() |
得到文本字符串 |
res.blob() |
得到二进制 Blob 对象 |
res.formData() |
得到 FormData 表单对象 |
res.arrayBuffer() |
得到二进制 ArrayBuffer 对象 |
1 2 3 4 5 6 7 8 9 10 11 12
| async function getData() { const res = await fetch('http://ajax-base-api-t.itheima.net/api/getbooks') console.log(res) console.log(res.ok) console.log(res.status) console.log(res.statusText) console.log(res.url)
let json = await res.json() console.log(json) } getData()
|
fetch 配置参数
参数介绍
fetch 的第一个参数是 url
,此外还可以接收第二个参数,作为配置对象,可以自定义发出的 HTTP 请求
比如:fetch(url,options)
其中:post、put、patch 用法类似,咱们这边以 post 为例演示
配置参数介绍:
1 2 3 4 5 6 7
| fetch(url,{ method:'请求方式,比如:post、delete、put', headers:{ 'Content-Type':'数据格式' }, body:'post请求体数据' })
|
fetch 发送 post 请求
咱们这边以开发中用的较多的 JSON 格式的情况为例
基本语法 1:json 格式(常用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
async function add() { let obj = { bookname: '魔法书之如何快速学好前端666666', author: '茵蒂克丝', publisher: '格兰芬多', }
let res = await fetch('http://ajax-base-api-t.itheima.net/api/addbook', { method: 'post', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(obj), })
let json = await res.json() console.log(json) } add()
|
基本语法 2: x-www-form-urlencoded 格式(了解)
1 2 3 4 5 6 7 8 9 10 11 12 13
| async function add1() { let res = await fetch(url, { method: 'post', headers: { 'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8', }, body: 'foo=bar&lorem=ipsum', })
let json = await res.json() console.log(json) } add1()
|
基本语法 3:formData 格式(了解)
1 2 3 4 5 6 7 8 9 10 11 12
| let form = document.querySelector('form')
async function add2() { let res = await fetch(url, { method: 'POST', body: new FormData(form), })
let json = await res.json() console.log(json) } add2()
|
fetch 请求函数封装
原生 fetch 虽然已经支持 promise 了,相比 XMLHttpRequest 已然好用了很多,但是参数还是需要自己处理,比较麻烦
比如:
目标效果:
1 2 3 4 5 6 7 8 9 10 11 12 13
| http({ method:'xxx' url:'xxx', params:{......} })
http({ method:'xxx' url:'xxx', data:{......} })
|
封装之后代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| async function http(obj) { let { method, url, params, data } = obj
if (params) { let str = new URLSearchParams(params).toString() url += '?' + str }
let res if (data) { res = await fetch(url, { method: method, headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data), }) } else { res = await fetch(url) } return res.json() }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
async function fn1() { let result1 = await http({ method: 'get', url: 'http://ajax-base-api-t.itheima.net/api/getbooks', params: { id: 1, }, }) console.log(result1) } fn1()
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
async function fn2() { let result2 = await http({ method: 'post', url: 'http://ajax-base-api-t.itheima.net/api/addbook', data: { bookname: '魔法书111666', author: '嘻嘻', publisher: '哈哈哈', }, }) console.log(result2) } fn2()
|
fetch 实战 - 图书管理案例
实例展示

接口文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 获取所有图书: 1、接口地址:http: 2、请求方式:get
添加图书: 1、接口地址:http: 2、请求方式:post 3、请求体参数: 1、bookname:图书的名称 2、author:作者 3、publisher:出版社
删除图书: 1、接口地址:http: 2、请求方式:delete 3、查询参数: 1、id:需要删除图片的id
|
HTML 结构
1 2 3 4 5 6 7 8 9 10
| <link rel="stylesheet" href="./lib/bootstrap-v4.6.0.css" /> <style> :root { font-size: 15px; }
body { padding-top: 15px; } </style>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| <div class="container-fluid"> <div class="row"> <div class="col-sm-8"> <table class="table table-bordered table-striped table-dark table-hover text-center"> <thead> <tr> <th scope="col">Id</th> <th scope="col">书名</th> <th scope="col">作者</th> <th scope="col">出版社</th> <th scope="col">操作</th> </tr> </thead> <tbody> <tr> <th scope="row">xxx</th> <td>xxx</td> <td>xxx</td> <td>xxx</td> <td> <button type="button" class="btn btn-link btn-sm">删除</button> </td> </tr> </tbody> </table> </div>
<div class="col-sm-4"> <div class="card text-white bg-secondary sticky-top"> <div class="card-header">添加新图书</div> <form class="card-body bg-light" id="addForm"> <div class="input-group mb-3"> <div class="input-group-prepend"> <span class="input-group-text">书名</span> </div> <input type="text" class="form-control" placeholder="请输入图书名称" name="bookname" /> </div> <div class="input-group mb-3"> <div class="input-group-prepend"> <span class="input-group-text">作者</span> </div> <input type="text" class="form-control" placeholder="请输入作者名字" name="author" /> </div> <div class="input-group mb-3"> <div class="input-group-prepend"> <span class="input-group-text">出版社</span> </div> <input type="text" class="form-control" placeholder="请输入出版社名称" name="publisher" /> </div> <button class="btn btn-dark" type="submit">添加</button> </form> </div> </div> </div> </div>
|
渲染功能
- 步骤:
- 把渲染的代码封装成函数
- 通过封装好的 http 函数,获取所有图书数据
- 遍历返回的图书数组,每遍历一项,就创建一个 tr 出来,拼接成完整字符串再一起添加到 tbody 中去
1 2
| let tbody = document.querySelector('tbody') let form = document.querySelector('form')
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| render()
async function render() { let res = await http({ method: 'get', url: 'http://ajax-base-api-t.itheima.net/api/getbooks', }) console.log(res.data)
let htmlStr = '' res.data.forEach((item) => { htmlStr += ` <tr> <th scope="row">${item.id}</th> <td>${item.bookname}</td> <td>${item.author}</td> <td>${item.publisher}</td> <td> <button type="button" class="btn btn-link btn-sm" data-id="${item.id}"> 删除 </button> </td> </tr> ` }) tbody.innerHTML = htmlStr }
|
添加功能
1
| <script src="./lib/form-serialize.js"></script>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| form.addEventListener('submit', async function (e) { e.preventDefault()
let result = serialize(form, { hash: true }) console.log(result)
let res = await http({ method: 'post', url: 'http://ajax-base-api-t.itheima.net/api/addbook', data: result, }) console.log(res)
if (res.status === 201) { render() form.reset() } else { alert(res.msg) } })
|
删除数据
- 步骤:
- 利用事件委托,给 tbody 注册点击事件
- 判断 e.target.tagName 是不是按钮
- 如果是按钮,则通过封装好的 http 函数发送请求删除数据
- 此时需要知道删除的这一项的 id,则再渲染 button 时就可以把 id 添加到 dom 结构上
- 判断是否删除成功,如果删除成功,则需要重新加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| tbody.addEventListener('click', async function (e) { if (e.target.tagName === 'BUTTON') { let res = await http({ method: 'delete', url: 'http://ajax-base-api-t.itheima.net/api/delbook', params: { id: e.target.dataset.id, }, }) if (res.status === 200) { render() } } })
|
完结撒花