FetchAPI 并不仅仅是一个用来发网络请求的fetch方法,它提供了
Request
和Response
(以及其他与网络请求有关的)对象的通用定义,这些定义取代了之前一的些比较分散的定义方式,一言以蔽之,web请求逐步规范起来了。
关于FetchAPI的一个简单的用例:
fetch(`url`,{
method:'get',
headers:{},
body:JSON.stringify({
name:'Andy'
})
}).then(response => {
return response.json()
}).then(res => {
console.log('结果在这里--->',res)
})
复制代码
上面的代码只是处理了服务端返回JSON
数据的情况,并没有考虑其他类型的响应数据:如果服务端返回了一个文件,上述代码就会出错:Uncaught SyntaxError: Unexpected end of JSON input
。
我本人对FetchAPI了解和使用很少,类似上述的一个报错引起了我的注意,于是抽空查了资料,才意识到它的革命性意义:规范web请求。
FetchAPI让网路请求更规范
首先,FetchAPI在语言层面定义了几个主要接口:
Request
表示一次网络请求Response
表现了一次网络请求的数据Headers
定义了请求头和响应头的一系列操作
可以将一次网络请求用下面的过程表示:
//创建请求request
//1.构造请求头
const headers = new Headers()
headers.append('content-type','application/json')
//2.构造request
const request = new Request('url',{
method:'get',
mode:'cors',//表示一次跨资源共享的请求
headers:headers,
//...
})
//发送
fetch(request).then(response => {
if(response.ok){
//一次ok的响应:200
}else{
//其他的响应: 4xx, 5xx
}
const contentType = response.headers.get('content-type')
//根据内容类型调用不同的方法 .blob(), .text(), .formData()
if(contentType === 'application/json'){
return response.json()
}else{
//...
}
},err=>{
//没有收到响应
/*
1. 网络故障导致发送失败
2. 超时
*/
}).then(res => {
console.log('结果在这里--->',res)
})
复制代码
上面我们通过构造函数明确了请求相关的模块:
- request
- headers
- response
然后Response
接口提供了ok
布尔属性方便判定响应的有效性。此外,可以指定请求的模式是跨域请求还是同源请求(mode
),指定是否携带凭证(credentials
),一切都变得可配置,相比XMLHttpRequest
里的处理方式优雅了不知多少。
另外,我们还可以构造自定义的response
:const res = new Response()
。
上述所有用到的API都属于FetchAPI
。
如何处理重定向
众所周知,Ajax里是没有重定向的概念的,因为它属于文档的布局异步更新,无法像传统的response那样直接把页面重定到某个路径。
前端要想在Ajax里引入重定向,只能通过服务端返回一些约定的数据(一般放到HttpHeader
里作为标记),js读取header进行客户端内页面导航。
FetchAPI
里考虑了这一点,将之规范化:
//服务端
...
//一个API接口的controller片段
res.status(302).redirect('/love')
...
//客户端
fetch(request).then(response => {
//response.redirected 表示该响应是否是重定向的
const isRedirected = response.redirected
const redirectedUrl = response.url
//客户端判定是否跳转
})
复制代码
这里我们无需前后端的任何额外数据约定,规范简洁了很多,不是吗?
如何处理超时问题
这里需要指出的是FetchAPI没有提供timeout
的定义,而是把控制权交给开发,虽减少了一些便利,但长远来看是提升了接口的健壮性。
我们可以通过AbortController
接口来处理fetch请求的超时
const abortController = new AbortController()
//10秒钟后终止关联的请求(超时间隔为10s)
setTimeout(()=>{
abortController.abort()
},10000)
fetch('/api/login', {
method: 'get',
signal:abortController.signal
}).then(res => {
},err=>{
console.log(`这里可以捕获到超时错误-->`,err)
})
复制代码
总结
FetchAPI本质上把之前Ajax上的一些零散的方式归纳、总结、拆分、提炼为一个个的独立模块,这些模块相辅相成,组合在一起支撑了web请求的架构。而每个模块又提供了很多便捷的操作方法。
如果你还没怎么用过FetchAPI,建议你试试.