lcs-axios v1.0.0
@lcs/http
基于 axios 进行二次封装,更简单、更统一地使用 axios。
核心类 @/utils/http/request 为方便,统一将@/utils/http/request 用lcsAxios表示
功能列表
- 封装调用方式统一的 GET/POST/PUT/DELETE/FORMDATA 方法
- 自定义接口调用失败时如何处理错误提示(可开关,支持全局开关和单个接口开关)
- 常见 HTTP 状态码的中英文提示 400/401/403/404/405/413/414/500/502/504(可配置) netErrorTip(boolean) netErrorTipFn(function)
- 自定义错误处理函数,可以根据状态码指定不同错误类型的自定义操作:如 403 跳转到指定页面 app内401作登录跳转
- hooks 方法 beforeHook(config) 接口请求前自定义操作:如可以在请求时给页面添加蒙层,加载中效果 afterHook(responce/error, isError) 接口返回后自定义操作:如取消 loading 效果、处理返回数据的数据结构等
- 兼容错误信息在 200 请求情况 指定获取状态码函数 getResStatus(resData),获取 response 中的错误码 指定获取错误消息函数 getResErrMsg(resData),获取 response 中的错误消息 指定获取返回最终数据函数 getResData(resData),获取 response 中的返回数据
- 兼容 200 情况下的错误统一处理(可配置)如:-1001 -703 -701 app内跳转到登录页面判断 支持全局开关和当个接口开关 codeErrorTip(boolean) codeErrorTipFn(function)
- validateStatus自主校验接口状态
- 配置可取消重复请求
- 在 new LcsAxios 实例时,配置cancelDuplicated: true可开启取消重复的请求
- 在 new LcsAxios 实例时,duplicatedKeyFn函数可配置统一的重复请求的标识
- 在请求时可自定义配置单个请求的重复标识duplicatedKey
- 在请求时可自定义配置单个请求的cancelDuplicated: true可开启取消重复的请求
- create axios默认参数,支持传入axiosConfig覆盖
{ timeout: 8000, responseType: 'json', headers: { 'content-type': 'application/x-www-form-urlencoded' } }
- 支持配置一些需要自动带入在接口参数中的全局参数 如platform 如全局参数和接口参数发送冲突,以接口参数为主
使用方式
import Request from './request'
import config from '@/config'
import getHeader from './header'
import errorHandlers from './errorHandlers'
// eslint-disable-next-line no-unused-vars
import { Dialog } from 'vant'
const platform = process.env.VUE_APP_INSURE_PLATFORM
const lcsAxiosConfig = {
errorHandlers,
cancelDuplicated: false,
codeErrorTipFn: (msg) => {
Dialog.alert({
title: '提示',
message: msg
})
}
}
const axiosConfig = {
baseURL: config.baseApi,
timeout: 8000,
headers: getHeader()
}
const request = new Request(lcsAxiosConfig, axiosConfig)
export default {
list: (params) => request.get('/user', params),
add: (params) => request.post('/user', params),
update: (id, params) => request.put(`/user/${id}`, params),
delete: (id) => request.delete(`/user/${id}`),
deletes: (params) => request.delete(`/user/`, params),
upload: (params) => request.formdata(`/user/`, params),
}
lcsAxiosConfig 支持以下配置:
// 请求报错提示
// 这里将net错误和code错误分开
netErrorTip = true,
netErrorTipFn = (message) => { console.error(message) },
// code错误是否提示
codeErrorTip = true,
// 报错提示函数
codeErrorTipFn = (message) => { console.error(message) },
errorHandlers = {
// 错误回调 response.status response.data.code
// 支持 400/401/403/404/405/413/414/500/502/504/任意其他 errno
// 401: () => {}
// 403: () => {}
// ...
},
// error msg language: 'zh-cn'/'en'
lang = 'zh-cn',
// 接口发送之前
beforeHook,
// 接口发送之后
afterHook,
// 获取接口的请求状态码。 -code
getResStatus,
// 或者接口的错误提示信息 -msg
getResErrMsg,
// 获取接口返回数据
getResData,
// 校验接口状态码
validateStatus,
// 是否取消重复请求
cancelDuplicated = true,
// 如果开启了取消重复请求,如何生成重复标识p
duplicatedKeyFn,
LcsAxios 实例支持 get/post/put/delete/formdata实例方法,并且调用方式统一。
request.get(path, params, config)
request.post(path, params, config)
request.put(path, params, config)
request.delete(path, params, config)
request.formdata(path, params, config)
path 为请求路径;
params 为请求参数,GET/FORMDATA 的参数也不用特殊处理,lcs-axios 会统一处理,其中formdata的 Content-Type 为 multipart/form-data;charset=UTF-8
自定义错误提示函数
当接口报错时,我们通常会对错误信息进行提示。LcsAxios 提供了统一的方式来处理错误消息。在 LcsAxiosConfig 中指定 netTipFn(errmsg) 和 codeTipFu(errmsg) 可以指定错误消息的处理方式,指定 netTip(布尔值、codeTip(布尔值)可以开关是否执行错误提示。
const request = new LcsAxios({
tipFn: () => alert
})
支持当个接口禁用tip
// 禁用 tip
request.get(path, params, { disableTip: true })
Tip:这里很重要。如果在errorHandlers中存在相应错误码的处理函数,则tipFn失效,优先使用errorHandlers中的处理函数,某些场景下我们需要对错误进行弹窗后处理,就需要用到errorHandlers 如:-1001 401 -703 -701
自定义错误处理函数
使用 axios 进行接口请求发生错误时,一般会有两种,一种是validateStatus不通过时(默认是 2xx 通过) ,另一种是所有接口错误信息都由 200 状态返回,返回结果中带有固定字段表示,如 code/msg
在接口请求的过程中,我们有时会需要对于对某些特殊的错误进行一些额外的操作,如 403 的时候跳转到无权限的错误提示页。
这时候,我们可以在配置中添加相应的错误处理函数errorHandlers,可以给不同的错误码指定不同的处理函数,并且支持自定义的 errorCode。
// request.js
const request = new VeryAxios({
errorHandlers: {
// 支持 400/401/403/404/405/413/414/500/502/504/任意其他 errno
401: () => {}
403: () => {}
// 任意自定义errno
1002: () => {}
},
})
禁用错误处理
request.get(path, params, { disableHandler: true })
Hooks
lcsAxios 在请求前和请求后都留了钩子,以备需要在这两个时机进行特殊的处理。
beforeHook(config) 接口请求前的钩子函数
在接口请求前触发,可以在请求时给页面添加蒙层,加载中效果。config参数是最后发送请求时的配置。
config 为引用传值,可以对该引用的值进行修改,修改后会影响提交的配置
afterHook(responce/error, isError) 接口返回后钩子函数
在接口请求返回后触发,可以进行取消 loading 效果、处理返回的数据结构等操作。其中第一个参数在请求成功时是接口返回的响应response,在接口失败时,是返回的错误对象。第二个参数标识是否是错误返回。
response 为引用传值,可以对该引用的值进行修改,如对返回的数据结构进行调整
通常我们会在实例化时进行通用的钩子函数定义。但可能存在某些特殊的请求,不需要执行 hooks,这时候我们可以在单独的请求中,指定是否禁用 hooks 以及禁用哪一个 hooks。
// 禁用全部 hooks request.GET(path, params, { veryConfig: { disableHooks: true } }) // 禁用 before hooks request.GET(path, params, { veryConfig: { disableHooks: { before: true } } }) // 禁用 afater hooks request.GET(path, params, { veryConfig: { disableHooks: { after: true } } })
配置可取消重复请求自动
如果开启了取消重复请求,但是没有配置duplicatedKeyFn 和 duplicatedKey,那么默认的重复请求标识为:${config.method}${config.url}。如果同时配置了duplicatedKeyFn 和 duplicatedKey,那么duplicatedKey的优先级高于duplicatedKeyFn
在 new LcsAxios 实例时,配置cancelDuplicated: true可开启取消重复的请求
const lcsAxiosConfig = {
cancelDuplicated: true,
}
const request = new LcsAxios(veryAxiosConfig)
在 new LcsAxios 实例时,duplicatedKeyFn函数可配置统一的重复请求的标识
const lcsAxiosConfig = {
cancelDuplicated: true,
duplicatedKeyFn: (config) => {
const { method, url, responseType } = config
return `${method}${url}${responseType}`
}
}
const request = new LcsAxios(lcsAxiosConfig)
在请求时的可自定义配置单个请求的重复标识duplicatedKey
request.get(path, params, { duplicatedKey: 'duplicatedKey' })
自定义错误信息及数据的获取
接口在返回错误时有两种常见方案,其中一种是全部 200 返回,通过特定字段标识是否是错误,如 code, 表示错误号,非 0 则为错误;msg 表示错误信息;data 为返回的数据。这也是 LcsAxios 的默认值。 有些时候,接口并非我们预想的这样统一,我们可以通过以下三个函数分别指定如何从 reponse data 中获取上述的三个值。
- getResStatus(resData),获取 response 中的错误码,默认值 (resData) => resData.code
- getResErrMsg(resData),获取 response 中的错误消息,默认值 (resData) => resData.msg
- getResData(resData),获取 response 中的返回数据,默认值 (resData) => resData.data
踩坑记录: 1.ajax发送json数据时设置contentType: "application/json”和不设置时到底有什么区别? contentType: "application/json”,首先明确一点,这也是一种文本类型(和text/json一样),表示json格式的字符串,如果ajax中设置为该类型,则发送的json对象必须要使用JSON.stringify进行序列化成字符串才能和设定的这个类型匹配。同时,对应的后端如果使用了Spring,接收时需要使用@RequestBody来注解,这样才能将发送过来的json字符串解析绑定到对应的 pojo 属性上。另外,需注意一点,json字符串在书写时名称部分需要加上“”双引号,以免一些json解析器无法识别。
如ajax 请求时不设置任何contentType,默认将使用contentType: "application/json”application/x-www-form-urlencoded,这种格式的特点就是,name/value 成为一组, 每组之间用 & 联接,而 name与value 则是使用 = 连接。如: www.baidu.com/query?user=username&pass=password 这是get请求, 而 post 请求则是使用请求体,参数不在 url 中,在请求体中的参数表现形式也是: user=username&pass=password的形式。使用这种contentType时,对于简单的json对象类型,如:{“a”:1,"b":2,"c":3} 这种,将也会被转成user=username&pass=password 这种形式发送到服务端。而服务端接收时就按照正常从from表单中接收参数那样接收即可,不需设置@RequestBody之类的注解。但对于复杂的json 结构数据,这种方式处理起来就相对要困难,服务端解析时也难以解析,所以,就有了application/json 这种类型,这是一种数据格式的申明,明确告诉服务端是什么格式的数据,服务端只需要根据这种格式的特点来解析数据即可。
2.post要将参数放在 config.data中!get请求参数为config.params。
3.在axios封装过程中,为了兼容不同平台的api,故在核心类request.js中不掺杂任何的业务代码,都是由外部传入。不同平台的api如果互相不兼容,则需要各种实例化request类。这次封装,旨在在多人协作上,摒弃copy代码式玩法,统一api封装风格,统一前端报错提示,统一用户体验。
LcsAxios 实例化参数
属性 | 说明 | 类型 | 默认值 | 备注 |
---|---|---|---|---|
netErrorTipFn | 接口状态非200报错回调函数 | Function | (message) => { console.error(message) } | - |
netErrorTip | 是否接口状态非200执行netErrorTipFn | Boolean | true | - |
codeErrorTipFn | 返回参数 code 非0报错回调函数 | Function | (message) => { console.error(message) } | - |
codeErrorTip | 是否返回参数 code 非0报错回调函数 | Function | (message) => { console.error(message) } | - |
lang | 错误提示中音文 | String | zh-cn | - |
beforeHook | 接口发送之前处理函数,参数axios.config | Function | (config) => log(config) | 在该hook中可带入一些全局参数,如platform,headers中的access-token |
afterHook | 接口发送之前处理函数,参数response | Function | res => {} | - |
errorHandlers | 错误码回调函数集合 | Object | {} | - |
getResStatus | 获取接口返回参数状态标示 | Function | res => res.code | - |
getResErrMsg | 获取接口的错误提示信息 | Function | res => res.msg | - |
getResData | 获取接口返回数据 | Function | res => res | - |
validateStatus | 校验接口是否为成功 | Function | code => code === 0 | - |
cancelDuplicated | 是否取消重复请求 | Boolean | true | - |
duplicatedKeyFn | 如果开启了取消重复请求,如何生成重复标识 | Function | config => ${config.method}${config.url} | - |
单个api配置参数 优先级高于实例化参数
属性 | 说明 | 类型 | 默认值 | 备注 |
---|
|disableHooks|是否禁用beforeHook、afterHook|Boolean|Object| - |-|
|disableHandler|是否禁用错误处理函数|Boolean| false
|-|
|disableQs|是否在post请求的时候参数不进行Qs转换|Boolean| false
|-|
|beforeHook|接口发送之前处理函数,参数axios.config,优先级高于LcsAxios实例化参数 |Function|-|-|
|afterHook|接口发送之前处理函数,参数response,优先级高于LcsAxios实例化参数 |Function|-|-|
|duplicatedKey| 重复请求标识 |String|-|-|
示例
import Request from './request'
import config from '@/config'
import getHeader from './header'
import { getToken } from '@/utils/auth'
import Vue from 'vue'
const vm = new Vue()
const showToast = (txt) => {
vm.$createToast({
time: 2000,
txt,
type: 'error'
}).show()
}
const platform = process.env.VUE_APP_INSURE_PLATFORM
const lcsAxiosConfig = {
cancelDuplicated: false,
netErrorTip: true,
codeErrorTip: true,
codeErrorTipFn: (msg) => {
showToast(msg)
},
netErrorTipFn: (msg) => {
showToast(msg)
}
}
const axiosConfig = {
baseURL: config.baseApi
}
export const http = new Request(
{
...lcsAxiosConfig,
beforeHook: (config) => {
const headers = getHeader()
config.params ? config.params.platform = platform : config.params = { platform }
config.headers = Object.assign({}, config.headers, headers)
}
}, axiosConfig)
export const sitHttp = new Request(
{
...lcsAxiosConfig,
getResStatus: (res) => res.success ? 0 : -1,
beforeHook: (config) => {
const accessToken = getToken()
const authorization = accessToken ? `Bearer ${accessToken}` : ''
config.headers = Object.assign({}, config.headers, { accessToken, authorization })
}
},
{
baseURL: config.sitApi
}
)
单个接口参数示例
// 获取用户信息
export async function getUserInfo (data) {
const url = '/security/user/getUserInfo'
return sitHttp.get(url, data, {
disableTip: true
})
}
export function loginByMobile ({ mobile, code }) {
const url = '/security/social/token'
const params = {
grant_type: 'mobile',
mobile,
code
}
return sitHttp.fetch({
url,
params,
method: 'post',
config: {
headers: {
Authorization: `Basic ${process.env.VUE_APP_AUTH_BASIC}`,
'Content-Type': 'application/x-www-form-urlencoded'
}
}
})
}
3 years ago