Stay before every beautiful thoughts.
Just be nice, always think twice!
浅谈fetch及跨域
由于 FetchAPI 是基于 Promise 设计,有必要先学习一下 Promise
语法说明
fetch(url, options).then((res) => {
// handle HTTP response
}).catch((err) => {
// handle network error
})
参数说明
url
定义要获取的资源。这可能是:
- 一个 USVString 字符串,包含要获取资源的 URL。
- 一个 Request 对象。
options(可选)
一个配置项对象,包括所有对请求的设置。可选的参数有:
- method: 请求使用的方法,如 GET、POST。
- headers: 请求的头信息,形式为 Headers 对象或 ByteString。
- body: 请求的 body 信息:可能是一个 Blob、BufferSource、FormData、URLSearchParams 或者 USVString 对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息。
- mode: 请求的模式,如 cors、 no-cors 或者 same-origin。
- credentials: 请求的 credentials,如 omit、same-origin 或者 include。
- cache: 请求的 cache 模式: default, no-store, reload, no-cache, force-cache, 或者 only-if-cached。
response
一个 Promise,resolve 时回传 Response 对象:
- 属性:
- status (number) - HTTP请求结果参数,在100–599 范围
- statusText (String) - 服务器返回的状态报告
- ok (boolean) - 如果返回200表示请求成功则为true
- headers (Headers) - 返回头部信息,下面详细介绍
- url (String) - 请求的地址
- 方法:
- text() - 以string的形式生成请求text
- json() - 生成JSON.parse(responseText)的结果
- blob() - 生成一个Blob
- arrayBuffer() - 生成一个ArrayBuffer
- formData() - 生成格式化的数据,可用于其他的请求
- 其他方法:
- clone()
- Response.error()
- Response.redirect()
response.headers
- has(name) (boolean) - 判断是否存在该信息头
- get(name) (String) - 获取信息头的数据
- getAll(name) (Array) - 获取所有头部数据
- set(name, value) - 设置信息头的参数
- append(name, value) - 添加header的内容
- delete(name) - 删除header的信息
- forEach(function(value, name){ … }, [thisContext]) - 循环读取header的信息
使用案例
- GET
fetch('/user').then((res) => {
return res.text()
}).then((res) => {
console.log(res)
})
- POST
fetch('/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'robot',
code: '198964',
})
}).then((res) => {
console.log(res)
})
封装fetch
/**
* 将对象转成 a=1&b=2的形式
* @param obj 对象
*/
function obj2String(obj, arr = [], idx = 0) {
for (let item in obj) {
arr[idx++] = [item, obj[item]]
}
return new URLSearchParams(arr).toString()
}
/**
* 真正的请求
* @param url 请求地址
* @param options 请求参数
* @param method 请求方式
*/
function commonFetcdh(url, options, method = 'GET') {
const searchStr = obj2String(options)
let initObj = {}
if (method === 'GET') { // 如果是GET请求,拼接url
url += '?' + searchStr
initObj = {
method: method,
credentials: 'include'
}
} else {
initObj = {
method: method,
credentials: 'include',
headers: new Headers({
'Accept': 'application/json',
'Content-Type': 'application/json'
}),
body: searchStr
}
}
fetch(url, initObj).then((res) => {
return res.json()
}).then((res) => {
return res
})
}
/**
* GET请求
* @param url 请求地址
* @param options 请求参数
*/
function GET(url, options) {
return commonFetcdh(url, options, 'GET')
}
/**
* POST请求
* @param url 请求地址
* @param options 请求参数
*/
function POST(url, options) {
return commonFetcdh(url, options, 'POST')
}
GET('https://www.xxxxxx.com/search/error.html', {a:1,b:2})
POST('https://www.xxxxxx.com/search/error.html', {a:1,b:2})
CORS跨域
如果服务器支持 CORS, 则在客户端设置相应的 Access-Control-Allow-Origin
即可得到数据。
let myHeaders = new Headers({
'Access-Control-Allow-Origin': '*',
'Content-Type': 'text/plain'
});
fetch(url, {
method: 'GET',
headers: myHeaders,
mode: 'cors'
}).then((res) => {
// TODO
})