123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- import axios from 'axios'
- import { Message, MessageBox } from 'element-ui'
- import router from '@/router'
- /**
- * 配置的优先顺序
- * 查找顺序:lib/defaults.js 中库的默认值 -----> 实例的 defaults 属性 -----> 请求的 config 参数
- * 优先级为查找的反序,如上顺序中,后面覆盖前面
- * 优先级:请求的 config 参数 -----> 实例的 defaults 属性 -----> lib/defaults.js 中库的默认值
- *
- * @type {AxiosInstance}
- */
- /**
- * 响应消息体
- * {
- * // `data` 由服务器提供的响应
- * data: {},
- * // `status` 来自服务器响应的 HTTP 状态码
- * status: 200,
- * // `statusText` 来自服务器响应的 HTTP 状态信息
- * statusText: 'OK',
- * // `headers` 服务器响应的头
- * headers: {},
- * // `config` 是为请求提供的配置信息
- * config: {},
- * // `request` 生成响应的请求
- * // It is the last ClientRequest instance in node.js (in redirects)
- * // and an XMLHttpRequest instance the browser
- * request: {}
- * }
- *
- */
- /**
- * Axios封装
- */
- class AxiosService {
- /**
- * 定义公共属性
- * @returns
- */
- buildOptions() {
- return {
- // ---------- 自定义配置 ----------
- // HTTP response消息体 {data: {}, status: 200, statusText: 'OK', headers: {}, config: {}, request: {}}
- // 服务端消息体 service body {code: '0', message: 'success', data: {page: 0, totalPage: 1, count: 0, totalCount: 0, rows: [{},{}]}
- // HTTP response消息体中response.data即是服务端消息体service body
- // service body中的data是服务端消息体中的业务数据 data
- // 解构分为,解构HTTP response消息体, 和解构服务端消息体service body(即解构response.data)
- // never, 不解构HTTP response消息体
- // serviceBody 和 serviceData, 一定会解构出HTTP response消息体中的data
- // 默认serviceBody, 解构HTTP response, 但不解构服务端消息体service body, 返回服务端消息体service body全部
- // serviceData, 解构HTTP response, 并解构出服务端消息体service body中的业务数据data
- // 配置值为 never | serviceBody(默认) | serviceData
- deconstruction: 'serviceBody',
- // ---------- 以下为原生配置 ----------
- // `url` 是用于请求的服务器 URL
- url: '',
- // `method` 是创建请求时使用的方法
- method: 'get', // 默认是 get
- // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
- // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
- // url = base url + request url, 区分开发环境和生产环境
- baseURL: '/api',
- // `headers` 是即将被发送的自定义请求头
- headers: { 'X-Requested-With': 'Songmao' },
- // `params` 是即将与请求一起发送的 URL 参数
- // 必须是一个无格式对象(plain object)或 URLSearchParams 对象
- params: {
- // xxx: yyy
- },
- // `data` 是作为请求主体被发送的数据
- // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
- // 在没有设置 `transformRequest` 时,必须是以下类型之一:
- // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
- // - 浏览器专属:FormData, File, Blob
- // - Node 专属: Stream
- data: {
- // xxx: yyy
- },
- // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
- // 如果请求话费了超过 `timeout` 的时间,请求将被中断
- timeout: 10000,
- // `withCredentials` 表示跨域请求时是否需要使用凭证,// 默认的false
- withCredentials: true,
- // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
- responseType: 'json', // 默认的
- // `onUploadProgress` 允许为上传处理进度事件
- onUploadProgress: function(progressEvent) {
- // 对原生进度事件的处理
- },
- // `onDownloadProgress` 允许为下载处理进度事件
- onDownloadProgress: function(progressEvent) {
- // 对原生进度事件的处理
- },
- // `maxContentLength` 定义允许的响应内容的最大尺寸
- maxContentLength: 2000,
- // `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte
- validateStatus: function(status) {
- return status >= 200 && status < 300 // 默认的
- },
- // 'proxy' 定义代理服务器的主机名称和端口
- // `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据
- // 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头。
- proxy: {
- // // e.g.
- // host: '127.0.0.1',
- // port: 8080
- // auth: : {
- // username: 'xxx',
- // password: 'yyy'
- // }
- }
- }
- }
- /**
- * 实例化 Axios
- */
- constructor() {
- // 实例化axios对象
- this.inst = axios.create(this.buildOptions())
- /**
- * request interceptor
- */
- this.inst.interceptors.request.use(
- config => {
- // do something before request is sent
- if (!config.deconstruction) {
- const xConfig = {
- // 默认从response中解构出服务端消息体
- deconstruction: 'serviceBody'
- }
- config = Object.assign({}, config, xConfig)
- }
- return config
- },
- error => {
- // do something with request error
- return Promise.reject(error)
- }
- )
- /**
- * response interceptor
- */
- this.inst.interceptors.response.use(
- response => {
- const { data, status, statusText, config } = response
- const deconstruction = config.deconstruction || 'serviceBody'
- // ---------- 返回response 消息体 ----------
- if (deconstruction === 'never') {
- return response => response
- }
- // ---------- 返回服务端消息体 ----------
- if (deconstruction === 'serviceBody') {
- if (status === 200) {
- return data
- } else {
- Message({
- type: 'error',
- title: '消息',
- message: statusText || 'Http Error',
- duration: 5 * 1000
- })
- return Promise.reject(new Error(statusText || 'Http Error'))
- }
- }
- // ---------- 返回服务端消息体中的data ----------
- if (!data) {
- Message({
- type: 'error',
- title: '消息',
- message: 'Error: HTTP消息体data为空',
- duration: 5 * 1000
- })
- return Promise.reject(new Error('Error: HTTP消息体data为空'))
- }
- const res = data
- if (!res.code) {
- Message({
- type: 'error',
- title: '消息',
- message: 'Error: 服务端未返回code',
- duration: 5 * 1000
- })
- return Promise.reject(new Error('Error: 服务端未返回code'))
- }
- if (res.code !== '0') {
- Message({
- type: 'error',
- title: '消息',
- message: res.message ? '【' + res.code + ':' + res.message + '】' : '业务异常',
- duration: 5 * 1000
- })
- // ---------- 服务端需要处理的消息码 ----------
- // 服务端自定义消息码处理
- // 100012: Illegal token, 100020: SESSION_EXPIRE
- if (res.code === '100012' || res.code === '100020') {
- MessageBox.confirm(res.message ? '【' + res.code + ':' + res.message + '】, 非法请求, 或会话过期' : '非法请求, 或会话过期', '警告', {
- type: 'warning',
- confirmButtonText: '确认',
- cancelButtonText: '取消'
- }).then(() => {
- router.push({ path: '/login' })
- })
- }
- // others server message code......
- return Promise.reject(new Error(res.message || '业务异常'))
- } else {
- // 返回服务端消息体Service Body 中的 data
- return res.data
- }
- },
- error => {
- Message({
- type: 'error',
- message: error.message,
- duration: 5 * 1000
- })
- return Promise.reject(error)
- }
- )
- }
- // ---------- 对外提供访问方法 ----------
- instance() {
- return this.inst
- }
- setOptions(options) {
- this.inst.defaults = Object.assign({}, this.inst.defaults, options)
- }
- request(options) {
- return this.inst.request(options)
- }
- get(url, options) {
- return this.inst.get(url, options)
- }
- post(url, options) {
- return this.inst.post(url, options)
- }
- }
- const Service = (() => new AxiosService())()
- export default Service
|