Fetch API
Fetch API 提供了一个用于获取资源(目前主要是网络资源)的接口。
比用 XMLHttpRequest 更强大、更灵活。
fetch 构建请求消息
url 和 method
调用浏览器内置的 fetch 函数,就可以 发送http请求,
第1个参数 resource
通常就是 url字符串
第2个参数 options
是一个可选参数,用来设置请求行为的
比如
fetch('/api/something'); // 缺省的 HTTP Method 是 GET
fetch(
"/api/something",
{
method: 'POST',
body : 'postdata.....'
}
);
url 参数
url query String 参数 就是 urlencode 格式
自己写代码拼接出 urlencode 格式的字符串比较麻烦,
可以使用浏览器内置的 URLSearchParams 类型。
URLSearchParams对象的方法 toString
,可以将对象序列化为 urlencoded 格式
比如:
var queryStr = new URLSearchParams({code:'6000001', time:'2022-02-23' }).toString()
fetch(`http://localhost/api/stock?${queryStr}`)
消息头
fetch 发送http请求要定制一些消息头,可以通过 options 参数里面的 headers
属性设置,如下
fetch(
'/api/something',
{
headers: {
username: "byhy",
password: "abcdefgh",
"Content-Type": "application/json"
}
}
)
消息体
fetch 的请求消息体都是参数对象 options
的 body
属性中设置的
如果有消息体,我们应该在 options
里面的 headers
中,用 Content-Type
指明消息体格式
如果没有指明,缺省为 text/plain;charset=UTF-8
urlencode 格式
消息体也可以是 urlencode 格式,同样可以使用 URLSearchParams
其实,如果使用jQuery发送请求, data参数如果是js 对象,缺省行为就是转化为 urlencode格式
所以可以直接传对象,如下
var username = 'byhy'
var password = '88888888'
var payload = new URLSearchParams(
{ username: username, password:password}).toString()
fetch(
'/api/mgr/signin',
{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: payload
}
)
当然,如果你觉得直接构建 urlencode格式的字符串不麻烦也可以直接构建,比如
var username = 'byhy'
var password = '88888888'
fetch(
'/api/mgr/signin',
{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: `username=${username}&password=${password}`
}
)
JSON 格式
现在的API接口消息体 很多是JSON格式的字符串。
可以使用浏览器js内置对象 JSON
JSON 的方法 stringify
可以序列化js对象为JSON格式
fetch(
'/api/mgr/signin',
{
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ username: 'byhy', password:'88888888' })
}
)
fetch 解析响应消息
fetch调用后,返回值是一个Promise对象。
如果成功获取服务端响应消息,这个Promise对象就会 resolve 一个 Response 对象
对这个Response对象的处理,自然应该在 Promise对象的then方法中
可以调用 Response对象的属性和方法获取响应消息中的数据
比如,
响应状态码
通过 Response对象的 status
属性获取响应状态码
fetch(
'/api/mgr/signin',
{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: `username=byhy&password=88888888`
}
)
.then(response => {
console.log(response.status)
})
响应消息头
通过 Response对象的 headers
属性获取响应消息头
该属性返回的是一个 Headers 类型的对象
可以通过 它的
-
entries() 方法遍历获取所有的消息头
-
get() 方法获取某个消息头
比如
fetch(
'/api/mgr/signin',
{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: `username=byhy&password=88888888`
}
)
.then(response => {
let headers = response.headers
// 遍历获取所有的消息头
for (const pair of headers.entries()) {
console.log(`${pair[0]}: ${pair[1]}`);
}
// 获取某个消息头
let ct = headers.get('content-type')
console.log(`content-type 为 ${ct}`);
})
响应消息体
HTTP响应消息体内容,通常是通过 Resonse对象的方法,比如 json()、text() 等方法获取
因为响应消息体可能会分批从网络发送回来,所以这些方法往往不是立即返回数据,而是返回一个Promise
响应消息体数据全部读取完毕后,再resolve这个Promise对象
json 格式
比如对json格式的响应消息体, 可以这样写
fetch(
'/api/mgr/signin',
{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: `username=byhy&password=88888888`
}
)
.then(response => {
return response.json()
})
.then(data => {
console.log(data)
})
可以简写为
fetch(
'/api/mgr/signin',
{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: `username=byhy&password=88888888`
}
)
.then(response => response.json())
.then(data => console.log(data))
通常,会在最后加上错误处理
如下:
fetch(
'/api/mgr/signin3',
{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: `username=byhy&password=88888888`
}
)
.then(response => response.json())
.then(data => console.log(data))
.catch(reason =>{console.log('登录认证出现错误:',reason)});
其它响应格式
如果返回的响应消息不是json格式,而是其它文本格式,比如XML
可以通过 text()方法,得到消息体原始字符串, 再自行进行后续的转化
注意:text()方法 返回的也是promise对象
可以这样处理:
fetch(
'/api/mgr/signin',
{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: `username=byhy&password=88888888`
}
)
.then(response => response.text())
.then(data => {
console.log('响应原始文本内容为:',data)
// 后面可以自己写代码对data进行处理
})
async/await
针对promise,更推荐的是 使用 async/await 语法糖
比如
var response = await fetch(
'/api/mgr/signin',
{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: `username=byhy&password=88888888`
}
)
var resObj = await response.json()
console.log('登录返回结果',resObj)
为什么 response.json() 前面也要加个 await
呢?
因为 response.json() 返回的也是promise , 所以要await
使用 async/await 更方便的是再接收到响应后,继续后续的消息发送和接收
比如
// 先登录
var response = await fetch(
'/api/mgr/signin',
{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: `username=byhy&password=88888888`
}
)
var resObj = await response.json()
console.log('登录返回结果',resObj)
// 再获取客户数据
if (resObj.ret === 0){
response = await fetch(
'/api/mgr/customers?action=list_customer&pagenum=1&pagesize=5')
resObj = await response.json();
console.log('获取客户数据结果',resObj)
}
fetch返回的promise 或者 response.json() 返回的promise,
如果其中任意一个失败了,对应的 await 会抛出 reject的结果对象,从而中断后续的代码执行。
可以通过 try… catch 捕获处理
比如
try{
// 先登录
var response = await fetch(
'/api/mgr/signin33',
{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: `username=byhy&password=88888888`
}
)
var resObj = await response.json() // 此处会抛异常
console.log('登录返回结果',resObj)
// 再获取客户数据
if (resObj.ret === 0){
response = await fetch(
'/api/mgr/customers?action=list_customer&pagenum=1&pagesize=5')
resObj = await response.json();
console.log('获取客户数据结果',resObj)
}
}
catch (error) {
console.log('捕获到错误', error)
// 下面写错误处理的代码
}