fetch的二次封装
2020-06-11 本文已影响0人
得到世界又如何我的心中只有你
前言
在请求方法这块,考虑到便捷性,针对不同的平台app web h5
以及对参数的处理,做了以下的方法封装。
内容
1.请求参数处理
2.响应code处理
3.处理数组、对象等特殊参数
4.跨域请求mode
5.拓展
执行
请求参数处理
这里主要使用到三种请求头类型:multipart/form-data、application/json、application/x-www-form-urlencoded
,针对不同的类型对参数做不同的处理
/**
* @param {*} params
* @param {*} ContentType
*/
function getUriParams(params = {}, contentType = 'multipart/form-data') {
// 请求参数
let uriParams = ''
switch (contentType) {
case 'multipart/form-data': // formData
uriParams = new FormData()
Object.keys(params).forEach(key => {
uriParams.append(key, params[key])
})
break
case 'application/json': // json
uriParams = JSON.stringify(params)
break
case 'application/x-www-form-urlencoded': // 键值对 key1=value1&key2=value2
Object.keys(params).forEach(key => {
uriParams += key + '=' + params[key] + '&'
})
uriParams = uriParams.substring(0, uriParams.length - 1)
break
default:
break
}
return uriParams
}
响应code处理
常用的200 404 500...,以及项目中单独定义的。
/**
* @param {Object} respResult
* @param {Function} resolve
* @param {Function} reject
*/
function responseCode(respResult = {}, resolve, reject) {
switch (respResult.code) {
case 200: // 成功
resolve(respResult.ret)
break
case 404: // 请求资源不存在
resolve({ msg: '请求资源不存在' })
break
case 500: // 服务器异常
resolve({ msg: '服务器异常' })
break
// 以下为项目中接口定义的code
case xxx: // 鉴权失败
doLogin()
break
// ... ...
default:
reject(respResult)
break
}
}
处理数组、对象等特殊参数
在请求类型为formData
时,请求携带参数格式为
id = 1
value = '1234'
// ... ...
当后端接受类型存在Map List
时,我们的请求参数格式可能为
params = {
list1: [1,2,3,4],
list2: [{id: 1, value: '1234'}],
obj1: {id: 1, value: '1234'}
// ... ...
}
而我们知道需要将数据调整成下面的方式才能被后端所识别
params['list1'][0] = 1
params['list1'][1] = 2
// ... ...
params['list2'][0]['id'] = 1
params['list2'][0]['value'] = '1234'
// ... ...
params['obj1']['id'] = 1
params['obj1']['value'] = '1234'
// ... ...
注意:针对图片格式则不用做相应处理
/**
* 参数处理(处理数组或对象的value,格式:数组arr[i]、对象obj.key)
* @param {*} params
*/
function manageParams(params) {
for (let key in params) {
let item = params[key]
if (item && item !== '' && item !== null && item !== undefined) {
if (Array.isArray(item)) {
// 数组
item.forEach((val, i) => {
if (val.constructor === Object || val.constructor === File || typeof val === 'string' || typeof val === 'number') {
params[`${key}[${i}]`] = val
}
})
delete params[key]
manageParams(params)
} else if (item.constructor === Object && !isImgFile(item)) {
// 对象
for (let i in item) {
params[`${key}.${i}`] = item[i]
}
delete params[key]
manageParams(params)
}
}
}
let allString = false
for (let key in params) {
let item = params[key] || ''
if (typeof item === 'string' || typeof item === 'number' || item === null || item.constructor === File) {
allString = true
}
}
if (allString) {
return params
}
}
// 非图片
function isImgFile(obj) {
if (obj['size'] && obj['type'] && obj['name']) {
return true
}
return false
}
跨域请求mode
fetch
支持cors
进行跨域访问,但如果header
中需要携带参数,会进行一个预检的过程,需要服务端设置允许请求头携带参数
// ... ...
let headers = new Header()
headers['Access-Control-Allow-Origin'] = '*'
headers['Content-Type'] = 'xxx'
// ... ...
fetch(url, {
method: 'POST',
headers,
mode: 'cors',
body: getUriParams(manageParams(params)),
}).then(() {
// ... ...
})
// ... ...
服务端设置
setHeader('Access-Control-Allow-Headers: Content-Type ... ...');
拓展
根据项目具体情况
1.参数可能放于body
或者header
中
return new Promise((reject, resolve) => {
fetch(url, {
method: 'POST',
headers: {
'Content-Type': ContentType,
platformType: 2,
osType: '',
version: ''
// ... ...
},
body: getUriParams(manageParams(params)),
credentials: 'include'
}).then((response) => {
Fetch.Fetch_last_url[url] = null
if (response.ok) {
return response.json()
} else {
reject({success: false, errCode:'500', errDesc: '服务器异常,请稍后重试'})
}
}).then((respResult) => {
responseCode(respResult, resolve, reject)
}).catch((error) => {
reject({success: false, errCode:'500', error: error.errDesc})
})
})
2.可能会使用到签名校验
function getSign(params) {
const CryptoJS = require('crypto-js')
// 密钥
let secret = '3f3**************************216' // 默认固定密钥
// 排序、加密(签名字段按照key正序,前后拼接密钥,MD5)
let paramsKeys = [], allParams = secret
Object.keys(params).forEach(key => paramsKeys.push(key))
paramsKeys.sort()
paramsKeys.forEach((key) => allParams += key + '=' + params[key] + '&')
allParams = allParams.substring(0, allParams.length - 1) + secret
return CryptoJS.MD5(allParams).toString()
}
3.请求和响应参数可能会进行加解密