/*
|
* @Author: Pengjiantian
|
* @Date: 2020-02-27 16:45:21
|
* @Last Modified by: Pengjiantian
|
* @Last Modified time: 2020-02-27 16:45:21
|
*/
|
|
// 基础请求封装
|
export default class BaseFetch {
|
/**
|
* constructor 构造函数
|
* @param {Object} conf 实例全局配置,配置项基本同 defaultConf
|
*/
|
constructor(conf = {}) {
|
this.defaultConf = {
|
timeout: 30000,
|
method: 'post',
|
headers: {
|
'Content-Type': 'application/json;charset=UTF-8'
|
}
|
}
|
|
this.specialBodyKeys = ['body', 'method', 'headers']
|
this.init(conf)
|
}
|
|
/**
|
* 初始化,合并配置
|
* @param {Object} conf 全局配置
|
*/
|
init(conf) {
|
const { defaultConf } = this
|
this.conf = Object.assign({}, { ...defaultConf }, { ...conf })
|
}
|
|
/**
|
* post 请求处理
|
* @param {String} api 接口地址
|
* @param {Object|String} body 请求参数
|
* @param {Object} conf 请求配置信息
|
*/
|
toPost(api, body = {}, conf = {}) {
|
return this.toFetch(api, body, { method: 'post', ...conf })
|
}
|
|
/**
|
* get 请求处理
|
* @param {String} api 接口地址
|
* @param {Object|String} body 请求参数
|
* @param {Object} conf 请求配置信息
|
*/
|
toGet(api, body = {}, conf = {}) {
|
return this.toFetch(api, body, { method: 'get', ...conf })
|
}
|
|
/**
|
* mixConf 合并配置项
|
* @param {Object} conf 请求配置项
|
* @param {Object} body 参数或包含参数的配置项 @example {data: {name: 'someone'}}
|
* @param {Object} conf 请求配置信息
|
*/
|
mixConf(api, body = {}, conf = {}) {
|
const { specialBodyKeys } = this
|
let mixConf = { ...this.conf, ...conf }
|
|
if (typeof body === 'string') {
|
mixConf = { ...mixConf, body }
|
}
|
if (typeof body === 'object') {
|
// body包含配置项,则body为配置信息
|
if (Object.keys(body).some(key => specialBodyKeys.includes(key))) {
|
mixConf = { ...mixConf, ...body }
|
} else {
|
mixConf = { ...mixConf, body }
|
}
|
}
|
|
const { method, body: mixBody, headers, ...other } = mixConf
|
const url = this.getUrl(api, mixConf)
|
let result =
|
headers === false
|
? { url, method, ...other }
|
: { url, method, headers, ...other }
|
|
if (method.toLocaleLowerCase() !== 'get') {
|
result = { ...result, body: this.getBody(mixConf) }
|
}
|
return result
|
}
|
|
/**
|
* joinPath拼接路径,去重中间重复连接符/
|
* @param {Array} pathArr 路径数组
|
* @param {Boolean} isReplaceFirst 是否去除第一个路径前的/
|
*/
|
joinPath(pathArr, isReplaceFirst = false) {
|
return pathArr.reduce((pre, curr, index) => {
|
const nextPath = curr.replace(/^\/+/, '')
|
curr = index === 0 && !isReplaceFirst ? curr : nextPath
|
pre = pre === '' ? curr : `${pre.replace(/\/+$/, '')}/${nextPath}`
|
return pre
|
}, '')
|
}
|
|
/**
|
* getUrl 获取请求url完整地址
|
* @param {String} api请求地址
|
* @param {Object} mixConf 混入后的请求配置
|
*/
|
getUrl(api, mixConf) {
|
const { method, body } = mixConf
|
if (method.toLocaleLowerCase() === 'get') {
|
const str = this.getUrlbody(api, body)
|
api = api.includes('?') ? `${api}&${str}` : `${api}?${str}`
|
}
|
return api
|
}
|
|
/**
|
* getUrlbody 拼接url字符串
|
* @param {String} api 接口地址
|
* @param {Object|String} body 请求参数
|
* @param {Object} conf 请求配置信息
|
*/
|
getUrlbody(api, body) {
|
if (typeof body === 'object') {
|
body = Object.keys(body).reduce((pre, curr) => {
|
const val =
|
typeof body[curr] === 'object'
|
? JSON.stringify(body[curr])
|
: body[curr]
|
pre = pre === '' ? pre : `${pre}&`
|
pre = `${pre}${curr}=${val}`
|
return pre
|
}, '')
|
}
|
return body
|
}
|
|
/**
|
* getBody 根据headers信息,
|
* @param {Object} mixConf 请求配置项
|
*/
|
getBody(mixConf) {
|
let { body, headers } = mixConf
|
if (typeof headers === 'object') {
|
Object.keys(headers).forEach(key => {
|
if (key.toLocaleLowerCase() === 'content-type') {
|
// json string
|
if (
|
headers[key].includes('application/json') &&
|
typeof body !== 'string'
|
) {
|
body = JSON.stringify(body)
|
}
|
|
// body
|
if (headers[key].includes('application/x-www-form-urlencoded')) {
|
body = this.getUrlbody(body)
|
}
|
|
// file
|
if (
|
headers[key].includes('multipart/form-data') &&
|
!(body instanceof FormData)
|
) {
|
const formData = new FormData()
|
Object.keys(body).forEach(key => {
|
formData.append(key, body[key])
|
})
|
}
|
}
|
})
|
}
|
return body
|
}
|
|
/**
|
* 请求统一入口
|
* @param {String} api 接口地址
|
* @param {Object|String} body 请求参数
|
* @param {Object} conf 请求配置信息
|
*/
|
toFetch(api, body = {}, conf = {}) {
|
const { url, ...other } = this.mixConf(api, body, conf)
|
return new Promise((resolve, reject) => {
|
fetch(url, other).then(res => {
|
if (res.ok) {
|
resolve(res.json())
|
}
|
reject(new Error(`接口:${url},请求异常!`))
|
})
|
})
|
}
|
}
|