fetch的使用
请求前的设置
所有主要的浏览器(除了Opera Mini和老的IE)都支持Fetch。针对不支持的,可以使用Fetch polyfil
fetch(' url ', requestData);
requestData 里面要 设置三个参数
第一个参数就是options,比如 get post 等等,默认为get。
第二个参数是请求头一般使用JSON数据格式,所以设置ContentType
为application/json
。
第三个参数是json 内容的主体,JSON.stringify(‘post请求下传递的参数对象’)
var requestData={
method:'POST',
headers: {
'Content-Type':'application/json',
'token':'asdasdasdasd',
},
body:JSON.stringify({data:111}),
}
这里使用了easy-mock 的模拟数据,
fetch('https://www.easy-mock.com/mock/5a18cb944a055229cab884e8/menu/listall',requestData)
这样就构建好了一次post请求的准别工作,mock 中返回的数据是一个json对象
终止请求
浏览器已开始为这些AbortController
和AbortSignal
接口(又名为Abort API)添加实验性支持,如果尚未完成,则允许中止Fetch和XHR等操作。
返回一个AbortSignal
对象实例,可用于与DOM请求进行通信/中止。
在DOM请求完成之前中止该请求。这可以中止获取请求,消耗任何响应Body
和流。
请求成功的处理
fetch的优点就在于
1.语法简单,
2.基于标准的Promise实现,支持async/await,
3.以及使用isomorphic-fetch
可以方便同构
一个fetch()
promise只有拒绝在遇到网络故障时(通常是当有一个权限问题或类似)。fetch()
不会拒绝对HTTP错误(404等)。相反,then
处理程序必须检查Response.ok
和/或 Response.status
属性。
注:意思就是HTTP 错误404等,在fetch的眼中不算是错误,它只负责返回服务器的response。
mock返回的响应是JSON格式的,所以调用response.json
方法来转换数据。
还有其他方法来处理不同类型的响应。如果请求一个XML格式文件,则调用response.text
。如果请求图片,使用response.blob
方法。
fetch('https://www.easy-mock.com/mock/5a18cb944a055229cab884e8/menu/listall',requestData)
.then(response=>{
return response.json()
}).then(data=>{
console.log(data);
}).then(error => console.log(error))
接下来我们要做的就是 处理response
目的:将所有异常情况抛出,获取正确数据到我们的页面中。
我们链接的接口最初设置的是post 请求 下面我在请求中将metchod:'get',或者将url拼错 导致404错误
var requestData={
method:'get',
headers: {
'Content-Type':'application/json',
'token':'asdasdasdasd',
},
body:JSON.stringify(),
}
返回的数据中 response.ok:false status:404 status:Not Found ,
最简单的办法就是判断response.ok 是否为true ,一旦我们知道请求是不成功的,我可以throw
异常或reject
Promise来调用catch
。
if (response.ok) {
return response.json()
} else {
// Find some way to get to execute .catch()
}
});
// throwing an Error
else {
throw new Error('something went wrong!')
}
// rejecting a Promise
else {
return Promise.reject('something went wrong!')
}
这样错误信息就可以自动进入catch中。于是在第一个.then中调用的函数应该这样写,用ok来判断是否获取到数据,当ok为false时候,将 response.status和response.statusText打包成一个包含错误信息的对象 一同推入catch中
function handleResponse (response) {
return response.json()
.then(json => {
if (response.ok) {
return json
} else {
return Promise.reject(Object.assign({}, json, {
status: response.status,
statusText: response.statusText
}))
}
})
}
- Fetch 请求默认是不带 cookie 的,需要设置
fetch(url, {credentials: 'include'})
- cookie 用于缓存用户信息,在不关闭浏览器的一段时间的情况下,关闭页面再重新打开不需要登陆。
- 服务器返回 400,500 错误码时并不会 reject,只有网络错误这些导致请求不能完成时,fetch 才会被 reject
处理其他响应类型
到现在,我们只处理JSON格式的响应,而返回JSON格式数据大约占90%。
至于其他的10%呢?
假设上面的例子返回的是XML格式的响应,也许会收到下面异常:
这是因为XML格式不是JSON格式,我们无法使用response.json
,事实上,我们需要response.text
,所以我们需要通过判断响应的头部来决定内容格式:
.then(response => {
let contentType = response.headers.get('content-type')
if (contentType.includes('application/json')) {
return response.json()
// ...
}
else if (contentType.includes('text/html')) {
return response.text()
// ...
}
else {
// Handle other responses accordingly...
}
});
这是我们到现在完整代码:
fetch('some-url')
.then(handleResponse)
.then(data => console.log(data))
.then(error => console.log(error))
function handleResponse (response) {
let contentType = response.headers.get('content-type')
if (contentType.includes('application/json')) {
return handleJSONResponse(response)
} else if (contentType.includes('text/html')) {
return handleTextResponse(response)
} else {
// Other response types as necessary. I haven't found a need for them yet though.
throw new Error(`Sorry, content-type ${contentType} not supported`)
}
}
function handleJSONResponse (response) {
return response.json()
.then(json => {
if (response.ok) {
return json
} else {
return Promise.reject(Object.assign({}, json, {
status: response.status,
statusText: response.statusText
}))
}
})
}
function handleTextResponse (response) {
return response.text()
.then(text => {
if (response.ok) {
return json
} else {
return Promise.reject({
status: response.status,
statusText: response.statusText,
err: text
})
}
})
}
参考资料:mdn:https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API