Vue encapsulated in axios

Vue encapsulated in axios

axios Vue is the official recommended a HTTP library, with the official introduction axios to introduce it, is this:

Axios is based on the promise of a HTTP library, you can use the browser and node.js in.

As a good HTTP library, axios defeated vue-resource has been maintained by the official team Vue, Vue won the right of authors, especially small strongly recommended to become the best choice for Vue project HTTP library.

Although, axios is a good HTTP library, however, directly in the project it is not so easy to use, so we need to configure package a certain degree, reduce duplication of code, easy call. Here, we have to talk in axios of Vue package.

Start

In fact, online lot codes on axios package, but most of them are in form axios global object attributes defined in the configuration file entry (main.js), similar to the following code:

axios.defaults.timeout = 10000

The program has two drawbacks, firstly, the code coupled Axios package file into the inlet inconvenient post-maintenance; secondly, Axios configured using global object attributes defined way, code is too fragmented.

For a problem, I used a large core idea Vue source structure - function as a file split, easy maintenance later. Create a separate  http.js or  http.ts file, and the file is introduced axios in its package configuration, finally the prototype, and mounted to the Vue. At this time, each modification axios configuration, only need to modify the corresponding file can not affect the unrelated functions.

For question two, using axios official recommendation to create axios instance by way of configuration items to configure package.

code show as below:

// http.js
import axios from 'axios'
// 创建 axios 实例 const service = axios.create({ // 配置项 })

According environment settings baseURL

baseURL address prefix request attribute is automatically added to the front url, unless the url is an absolute address. Under normal circumstances, and in production mode has a different baseURL in the development environment, so we need to switch to a different baseURL according to different environments.

In development mode, because there has devServer, the need for a request based on a fixed address prefix url rewrite, so, in the development environment, will baseURL set to a fixed value, such as: /apis.

In the production mode, according to different requests prefixes Java module may be provided different baseURL.

Specific code as follows:

// 根据 process.env.NODE_ENV 区分状态,切换不同的 baseURL
const service = axios.create({
    baseURL: process.env.NODE_ENV === 'production' ? `/java` : '/apis', })

Unified set of request headers

Here and we talk a question, what is the package? In my opinion, the package is covered scene more calls with fewer calling code.

Since, in most cases, request headers are fixed, at only a few cases, will need some special request headers, so, here, I used program is the universal request header as a base configuration. When required special request headers, the special request headers as a parameter, covering basic configuration.

code show as below:

const service = axios.create({
    ...
    headers: {
        get: {
          'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
          // 在开发中,一般还需要单点登录或者其他功能的通用请求头,可以一并配置进来 }, post: { 'Content-Type': 'application/json;charset=utf-8' // 在开发中,一般还需要单点登录或者其他功能的通用请求头,可以一并配置进来 } }, })

Cross-domain, time-out, response code processing

axios provided property --withCredentials whether to allow cross-domain, and configuration properties --timeout timeout by these two attributes, it can easily handle cross-domain and time-out problems.

Below, we say it is a response code processing:

axios provided validateStatus property to define for a given HTTP response status code is resolve or reject promise. Therefore, under normal setting, we will request a status code 304 is set to 2 or resolve the series state, the remaining state is reject. The result is that we can in the business code, unified response is captured using the catch bad request, thereby uniformly processing.

However, since I use the code inside the async-await, but we all know, async-await capture great way to catch trouble, so, here, I chose all responses are set to resolve state, then unified process.

This part of the code as follows:

const service = axios.create({
    // 跨域请求时是否需要使用凭证
    withCredentials: true,
    // 请求 30s 超时
    timeout: 30000, validateStatus: function () { // 使用async-await,处理reject情况较为繁琐,所以全部返回resolve,在业务代码中处理异常 return true }, })

Request, the response processing

Axios without the use of, in response to each request or receive, request or response needs to be serialized.

In axios, the  transformRequest allowed request to the server before sending, data modification request; transformResponse before transfer to then / catch, allows modification of the response data.

By these two hooks, we can save a lot of repeated code sequence.

code show as below:

const service = axios.create({
    // 在向服务器发送请求前,序列化请求数据
    transformRequest: [function (data) { data = JSON.stringify(data) return data }], // 在传递给 then/catch 前,修改响应数据 transformResponse: [function (data) { if (typeof data === 'string' && data.startsWith('{')) { data = JSON.parse(data) } return data }] })

Interceptor

Blocker, into a request and a response interceptor interceptors, then are intercepted before they are processed or catch request or response.

Mentioned before, since the catch async-await a difficult issue, it is also the case where the error is treated as a resolve status. However, this poses a problem, in response to a request or in case of error, the result is not msg field (message) defined in the data protocol. So, we need to when something goes wrong, manually generate a return in line with the format of the returned data.

Because, in business, there is no need to do additional processing requirements in the request interceptor, so, resolve the status request interceptors, just returned directly on it.

Request interceptor code is as follows:

// 请求拦截器
service.interceptors.request.use((config) => {
    return config
}, (error) => {
    // 错误抛到业务代码 error.data = {} error.data.msg = '服务器异常,请联系管理员!' return Promise.resolve(error) })

Come talk response interceptor, or that problem before, in addition to a request or response error, there is a situation would result in the return of the body of the message does not meet the protocol specification, that is, the status code is not 2 or 304 series. At this point, we still need to do the same process - manually generate a return in line with the format of the returned data. However, one thing is not the same, we also need to generate a different message depending on the status code to facilitate the issue after the treatment line.

Interceptor response code is as follows:

// 根据不同的状态码,生成不同的提示信息
const showStatus = (status) => {
    let message = '' // 这一坨代码可以使用策略模式进行优化 switch (status) { case 400: message = '请求错误(400)' break case 401: message = '未授权,请重新登录(401)' break case 403: message = '拒绝访问(403)' break case 404: message = '请求出错(404)' break case 408: message = '请求超时(408)' break case 500: message = '服务器错误(500)' break case 501: message = '服务未实现(501)' break case 502: message = '网络错误(502)' break case 503: message = '服务不可用(503)' break case 504: message = '网络超时(504)' break case 505: message = 'HTTP版本不受支持(505)' break default: message = `连接出错(${status})!` } return `${message},请检查网络或联系管理员!` } // 响应拦截器 service.interceptors.response.use((response) => { const status = response.status let msg = '' if (status < 200 || status >= 300) { // 处理http错误,抛到业务代码 msg = showStatus(status) if (typeof response.data === 'string') { response.data = { msg } } else { response.data.msg = msg } } return response }, (error) => { // 错误抛到业务代码 error.data = {} error.data.msg = '请求超时或服务器异常,请检查网络或联系管理员!' return Promise.resolve(error) })

tips: Tips, on top of that lump of switch-case code, you can use the strategy pattern to optimize ~

Support TypeScript

Since some time ago, I pushed TypeScript within the department, in order to satisfy their obsessive-compulsive disorder, all the js file to overwrite the file ts. Because axios itself TypeScript related support, so just need to import the corresponding type, and then assigned to.

The complete code

// http.ts
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'

const showStatus = (status: number) => { let message = '' switch (status) { case 400: message = '请求错误(400)' break case 401: message = '未授权,请重新登录(401)' break case 403: message = '拒绝访问(403)' break case 404: message = '请求出错(404)' break case 408: message = '请求超时(408)' break case 500: message = '服务器错误(500)' break case 501: message = '服务未实现(501)' break case 502: message = '网络错误(502)' break case 503: message = '服务不可用(503)' break case 504: message = '网络超时(504)' break case 505: message = 'HTTP版本不受支持(505)' break default: message = `连接出错(${status})!` } return `${message},请检查网络或联系管理员!` } const service = axios.create({ // 联调 baseURL: process.env.NODE_ENV === 'production' ? `/` : '/apis', headers: { get: { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8' }, post: { 'Content-Type': 'application/json;charset=utf-8' } }, // 是否跨站点访问控制请求 withCredentials: true, timeout: 30000, transformRequest: [(data) => { data = JSON.stringify(data) return data }], validateStatus () { // 使用async-await,处理reject情况较为繁琐,所以全部返回resolve,在业务代码中处理异常 return true }, transformResponse: [(data) => { if (typeof data === 'string' && data.startsWith('{')) { data = JSON.parse(data) } return data }] }) // 请求拦截器 service.interceptors.request.use((config: AxiosRequestConfig) => { return config }, (error) => { // 错误抛到业务代码 error.data = {} error.data.msg = '服务器异常,请联系管理员!' return Promise.resolve(error) }) // 响应拦截器 service.interceptors.response.use((response: AxiosResponse) => { const status = response.status let msg = '' if (status < 200 || status >= 300) { // 处理http错误,抛到业务代码 msg = showStatus(status) if (typeof response.data === 'string') { response.data = {msg} } else { response.data.msg = msg } } return response }, (error) => { // 错误抛到业务代码 error.data = {} error.data.msg = '请求超时或服务器异常,请检查网络或联系管理员!' return Promise.resolve(error) }) export default service
 

Vue encapsulated in axios

axios Vue is the official recommended a HTTP library, with the official introduction axios to introduce it, is this:

Axios is based on the promise of a HTTP library, you can use the browser and node.js in.

As a good HTTP library, axios defeated vue-resource has been maintained by the official team Vue, Vue won the right of authors, especially small strongly recommended to become the best choice for Vue project HTTP library.

Although, axios is a good HTTP library, however, directly in the project it is not so easy to use, so we need to configure package a certain degree, reduce duplication of code, easy call. Here, we have to talk in axios of Vue package.

Start

In fact, online lot codes on axios package, but most of them are in form axios global object attributes defined in the configuration file entry (main.js), similar to the following code:

axios.defaults.timeout = 10000

The program has two drawbacks, firstly, the code coupled Axios package file into the inlet inconvenient post-maintenance; secondly, Axios configured using global object attributes defined way, code is too fragmented.

For a problem, I used a large core idea Vue source structure - function as a file split, easy maintenance later. Create a separate  http.js or  http.ts file, and the file is introduced axios in its package configuration, finally the prototype, and mounted to the Vue. At this time, each modification axios configuration, only need to modify the corresponding file can not affect the unrelated functions.

For question two, using axios official recommendation to create axios instance by way of configuration items to configure package.

code show as below:

// http.js
import axios from 'axios'
// 创建 axios 实例 const service = axios.create({ // 配置项 })

According environment settings baseURL

baseURL address prefix request attribute is automatically added to the front url, unless the url is an absolute address. Under normal circumstances, and in production mode has a different baseURL in the development environment, so we need to switch to a different baseURL according to different environments.

In development mode, because there has devServer, the need for a request based on a fixed address prefix url rewrite, so, in the development environment, will baseURL set to a fixed value, such as: /apis.

In the production mode, according to different requests prefixes Java module may be provided different baseURL.

Specific code as follows:

// 根据 process.env.NODE_ENV 区分状态,切换不同的 baseURL
const service = axios.create({
    baseURL: process.env.NODE_ENV === 'production' ? `/java` : '/apis', })

Unified set of request headers

Here and we talk a question, what is the package? In my opinion, the package is covered scene more calls with fewer calling code.

Since, in most cases, request headers are fixed, at only a few cases, will need some special request headers, so, here, I used program is the universal request header as a base configuration. When required special request headers, the special request headers as a parameter, covering basic configuration.

code show as below:

const service = axios.create({
    ...
    headers: {
        get: {
          'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
          // 在开发中,一般还需要单点登录或者其他功能的通用请求头,可以一并配置进来 }, post: { 'Content-Type': 'application/json;charset=utf-8' // 在开发中,一般还需要单点登录或者其他功能的通用请求头,可以一并配置进来 } }, })

Cross-domain, time-out, response code processing

axios provided property --withCredentials whether to allow cross-domain, and configuration properties --timeout timeout by these two attributes, it can easily handle cross-domain and time-out problems.

Below, we say it is a response code processing:

axios provided validateStatus property to define for a given HTTP response status code is resolve or reject promise. Therefore, under normal setting, we will request a status code 304 is set to 2 or resolve the series state, the remaining state is reject. The result is that we can in the business code, unified response is captured using the catch bad request, thereby uniformly processing.

However, since I use the code inside the async-await, but we all know, async-await capture great way to catch trouble, so, here, I chose all responses are set to resolve state, then unified process.

This part of the code as follows:

const service = axios.create({
    // 跨域请求时是否需要使用凭证
    withCredentials: true,
    // 请求 30s 超时
    timeout: 30000, validateStatus: function () { // 使用async-await,处理reject情况较为繁琐,所以全部返回resolve,在业务代码中处理异常 return true }, })

Request, the response processing

Axios without the use of, in response to each request or receive, request or response needs to be serialized.

In axios, the  transformRequest allowed request to the server before sending, data modification request; transformResponse before transfer to then / catch, allows modification of the response data.

By these two hooks, we can save a lot of repeated code sequence.

code show as below:

const service = axios.create({
    // 在向服务器发送请求前,序列化请求数据
    transformRequest: [function (data) { data = JSON.stringify(data) return data }], // 在传递给 then/catch 前,修改响应数据 transformResponse: [function (data) { if (typeof data === 'string' && data.startsWith('{')) { data = JSON.parse(data) } return data }] })

Interceptor

Blocker, into a request and a response interceptor interceptors, then are intercepted before they are processed or catch request or response.

Mentioned before, since the catch async-await a difficult issue, it is also the case where the error is treated as a resolve status. However, this poses a problem, in response to a request or in case of error, the result is not msg field (message) defined in the data protocol. So, we need to when something goes wrong, manually generate a return in line with the format of the returned data.

Because, in business, there is no need to do additional processing requirements in the request interceptor, so, resolve the status request interceptors, just returned directly on it.

Request interceptor code is as follows:

// 请求拦截器
service.interceptors.request.use((config) => {
    return config
}, (error) => {
    // 错误抛到业务代码 error.data = {} error.data.msg = '服务器异常,请联系管理员!' return Promise.resolve(error) })

Come talk response interceptor, or that problem before, in addition to a request or response error, there is a situation would result in the return of the body of the message does not meet the protocol specification, that is, the status code is not 2 or 304 series. At this point, we still need to do the same process - manually generate a return in line with the format of the returned data. However, one thing is not the same, we also need to generate a different message depending on the status code to facilitate the issue after the treatment line.

Interceptor response code is as follows:

// 根据不同的状态码,生成不同的提示信息
const showStatus = (status) => {
    let message = '' // 这一坨代码可以使用策略模式进行优化 switch (status) { case 400: message = '请求错误(400)' break case 401: message = '未授权,请重新登录(401)' break case 403: message = '拒绝访问(403)' break case 404: message = '请求出错(404)' break case 408: message = '请求超时(408)' break case 500: message = '服务器错误(500)' break case 501: message = '服务未实现(501)' break case 502: message = '网络错误(502)' break case 503: message = '服务不可用(503)' break case 504: message = '网络超时(504)' break case 505: message = 'HTTP版本不受支持(505)' break default: message = `连接出错(${status})!` } return `${message},请检查网络或联系管理员!` } // 响应拦截器 service.interceptors.response.use((response) => { const status = response.status let msg = '' if (status < 200 || status >= 300) { // 处理http错误,抛到业务代码 msg = showStatus(status) if (typeof response.data === 'string') { response.data = { msg } } else { response.data.msg = msg } } return response }, (error) => { // 错误抛到业务代码 error.data = {} error.data.msg = '请求超时或服务器异常,请检查网络或联系管理员!' return Promise.resolve(error) })

tips: Tips, on top of that lump of switch-case code, you can use the strategy pattern to optimize ~

Support TypeScript

Since some time ago, I pushed TypeScript within the department, in order to satisfy their obsessive-compulsive disorder, all the js file to overwrite the file ts. Because axios itself TypeScript related support, so just need to import the corresponding type, and then assigned to.

The complete code

// http.ts
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'

const showStatus = (status: number) => { let message = '' switch (status) { case 400: message = '请求错误(400)' break case 401: message = '未授权,请重新登录(401)' break case 403: message = '拒绝访问(403)' break case 404: message = '请求出错(404)' break case 408: message = '请求超时(408)' break case 500: message = '服务器错误(500)' break case 501: message = '服务未实现(501)' break case 502: message = '网络错误(502)' break case 503: message = '服务不可用(503)' break case 504: message = '网络超时(504)' break case 505: message = 'HTTP版本不受支持(505)' break default: message = `连接出错(${status})!` } return `${message},请检查网络或联系管理员!` } const service = axios.create({ // 联调 baseURL: process.env.NODE_ENV === 'production' ? `/` : '/apis', headers: { get: { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8' }, post: { 'Content-Type': 'application/json;charset=utf-8' } }, // 是否跨站点访问控制请求 withCredentials: true, timeout: 30000, transformRequest: [(data) => { data = JSON.stringify(data) return data }], validateStatus () { // 使用async-await,处理reject情况较为繁琐,所以全部返回resolve,在业务代码中处理异常 return true }, transformResponse: [(data) => { if (typeof data === 'string' && data.startsWith('{')) { data = JSON.parse(data) } return data }] }) // 请求拦截器 service.interceptors.request.use((config: AxiosRequestConfig) => { return config }, (error) => { // 错误抛到业务代码 error.data = {} error.data.msg = '服务器异常,请联系管理员!' return Promise.resolve(error) }) // 响应拦截器 service.interceptors.response.use((response: AxiosResponse) => { const status = response.status let msg = '' if (status < 200 || status >= 300) { // 处理http错误,抛到业务代码 msg = showStatus(status) if (typeof response.data === 'string') { response.data = {msg} } else { response.data.msg = msg } } return response }, (error) => { // 错误抛到业务代码 error.data = {} error.data.msg = '请求超时或服务器异常,请检查网络或联系管理员!' return Promise.resolve(error) }) export default service

Guess you like

Origin www.cnblogs.com/whoamimy/p/11813873.html