I. Packaging of axios


In the vue project, and the backend interaction to get data this piece, we usually use the axios library, which is based on the promise http library, can run in the browser side and node.js. He has a lot of good features, such as intercepting requests and responses, cancel requests, convert json, client-side defense against XSRF and so on. So our You Da also decisively abandoned the maintenance of its official library vue-resource, directly recommend that we use axios library. If you still do not understand axios, you can move axios documentation.

npm install axios; //axios


Generally I will be in the project’s src directory, create a new request folder, and then in the new http.js and an api.js file. http.js file is used to encapsulate our axios, api.js is used to unify the management of our interface.


import axios from 'axios'; //axios

import QS from 'qs';

import { Toast } from 'vant'; 

  Switching of environments


Our project environment may have a development environment, a test environment and a production environment. We match our default interface url prefixes with node’s environment variables. axios.defaults.baseURL sets the default request address for axios without going into details.

// 环境的切换
if (process.env.NODE_ENV == 'development') {    
    axios.defaults.baseURL = 'https://www.discountstaken.com';} 
else if (process.env.NODE_ENV == 'debug') {    
    axios.defaults.baseURL = 'https://www.ceshi.com';
} 
else if (process.env.NODE_ENV == 'production') {    
    axios.defaults.baseURL = 'https://www.production.com';
}

  Setting the request timeout


Set the default request timeout via axios.defaults.timeout. For example, if it exceeds 10s, it will tell the user that the current request timed out, please refresh, etc.

axios.defaults.timeout = 10000;

 Post request header settings


When posting a request, we need to add a request header, so you can make a default setting here, i.e., set the request header of the post to be application/x-www-form-urlencoded;charset=UTF-8

axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
  •  Request Interception


We can do a request interception before sending a request, why do we need to intercept it, we intercept the request is used for what? For example, some requests require the user to be logged in before they can be accessed, or when posting a request, we need to serialize the data we submit. At this point, we can intercept a request before it is sent, so that we can perform the desired operation.

 Request Interception


import store from '@/store/index';

axios.interceptors.request.use(    
    config => {        

        const token = store.state.token;        
        token && (config.headers.Authorization = token);        
        return config;    
    },    
    error => {        
        return Promise.error(error);    
})


Here we talk about token, generally after the login is completed, the user’s token is stored locally via localStorage or cookie, then each time the user enters the page (i.e. in main.js), it will first read the token from the local storage, and if the token exists indicating that the user is logged in, then it will update the vuex’s If the token exists, the user is logged in, and the token status is updated in the vuex. Then, every time you request the interface, you will carry the token in the header of the request, and the backend staff can judge whether your login is expired according to the token you carry, if you don’t carry it, it means that you haven’t logged in. At this time, perhaps some partners will have questions, that is, each request to carry the token, then if a page does not require the user to log in to access how to do it? In fact, your front-end request can carry a token, but the background can choose not to receive ah!

 Response Interception


axios.interceptors.response.use(    
    response => {   

        if (response.status === 200) {            
            return Promise.resolve(response);        
        } else {            
            return Promise.reject(response);        
        }    
    },    

    error => {            
        if (error.response.status) {            
            switch (error.response.status) {                

                case 401:                    
                    router.replace({                        
                        path: '/login',                        
                        query: { 
                            redirect: router.currentRoute.fullPath 
                        }
                    });
                    break;


                case 403:
                     Toast({
                        message: 'Login expired, please login again',
                        duration: 1000,
                        forbidClick: true
                    });
                    localStorage.removeItem('token');
                    store.commit('loginSuccess', null);
                    setTimeout(() => {                        
                        router.replace({                            
                            path: '/login',                            
                            query: { 
                                redirect: router.currentRoute.fullPath 
                            }                        
                        });                    
                    }, 1000);                    
                    break; 

                case 404:
                    Toast({
                        message: 'Network request does not exist',
                        duration: 1500,
                        forbidClick: true
                    });
                    break;
                default:
                    Toast({
                        message: error.response.data.message,
                        duration: 1500,
                        forbidClick: true
                    });
            }
            return Promise.reject(error.response);
        }
    }    
});


Response interceptor is very good to understand, is the server to return to our data, we can get before he did some processing. For example, the above idea: if the status code returned by the background is 200, then the normal return data, otherwise, according to the type of error status code for some of the errors we need, in fact, here is the main error is the unified processing and not logged in or logged in after the expiration of the adjustment of the login page of an operation.


It is important to note that the Toast() method above, is the toast light hint component from the vant library that I introduced, and you use one of your hint components according to your ui library, correspondingly.

 Encapsulate get and post methods


We commonly used ajax request methods get, post, put and other methods, I believe that the partners will not be unfamiliar. axios corresponds to a lot of similar methods, it is not clear that you can look at the document. But in order to simplify our code, we still need to do a simple package. Here we mainly encapsulate two methods: get and post.


get method: we define a get function, get function has two parameters, the first parameter indicates that we want to request the url address, the second parameter is that we want to carry the request parameters. get function returns a promise object, when axios its request is successful resolve the server return value, the request fails to reject the error value. Finally, the get function is thrown by export.


export function get(url, params){    
    return new Promise((resolve, reject) =>{        
        axios.get(url, {            
            params: params        
        }).then(res => {
            resolve(res.data);
        }).catch(err =>{
            reject(err.data)        
    })    
});}

 


post method: the principle of the same get basically the same, but it should be noted that the post method must be used to submit from the parameter object to serialize the operation, so here we through the node qs module to serialize our parameters. This is very important, if there is no serialization operation, the background is not to get the data you submit. This is the reason we import QS from ‘qs’; at the beginning of the article.

export function post(url, params) {
    return new Promise((resolve, reject) => {
         axios.post(url, QS.stringify(params))
        .then(res => {
            resolve(res.data);
        })
        .catch(err =>{
            reject(err.data)
        })
    });
}


Here is a small detail to say, axios.get() method and axios.post() in the submission of data parameters are written in a different way. The difference is that the second parameter of get is a {}, and then the value of the params property of this object is a parameter object. The second parameter of post is a parameter object. Slight difference between the two to pay attention to oh!


axios package is basically completed, the following is a brief description of the unified management of api.


A neatly organized api is like a circuit board, even if it’s complicated, the whole line is clear. As mentioned above, we will create a new api.js, and then store all our api interfaces in this file.


  • First we introduce our wrapped get and post methods in api.js

import { get, post } from './http'


Now, let’s say we have an interface like this, which is a POST request:

http://www.baiodu.com/api/v1/users/my_address/address_edit_before

  We can wrap it like this in api.js:

export const apiAddress = p => post('api/v1/users/my_address/address_edit_before', p);


We define a apiAddress method that takes one parameter, p, which is the parameter object we carry when requesting the interface. Then we call our encapsulated post method. The first parameter of the post method is the address of our interface, and the second parameter is the p parameter of apiAddress , which is the parameter object we carry when requesting the interface. Finally, we export apiAddress via export.

 Then in our page we can call our api interface like this:

import { apiAddress } from '@/request/api';//api
export default {        
    name: 'Address',    
    created () {
        this.onLoad();
    },
    methods: {            
        onLoad() {
            apiAddress({                    
                type: 0,                    
                sort: 1                
            }).then(res => {
                ………………                
            })            
        }        
    }
}


Other api interfaces, just continue to expand down in pai.js can be. Friendly reminder to write good comments for each interface Oh!!!!


One of the benefits of api interface management is that we unify and centralize the api, and if we need to modify the interface at a later stage, we can just find the corresponding modification directly in api.js, instead of having to go to each page to find our interface and then modify it will be very troublesome. The point is, in case the amount of modification is relatively large, the specification gg. There is also the fact that if we modify the interface directly in our business code, it is easy to accidentally move to our business code causing unnecessary trouble.

 OK, finally the finished axios wrapper code is presented.


import axios from 'axios';import QS from 'qs';
import { Toast } from 'vant';
import store from '../store/index'


if (process.env.NODE_ENV == 'development') {    
    axios.defaults.baseURL = '/api';
} else if (process.env.NODE_ENV == 'debug') {    
    axios.defaults.baseURL = '';
} else if (process.env.NODE_ENV == 'production') {    
    axios.defaults.baseURL = 'http://api.123dailu.com/';
}


axios.defaults.timeout = 10000;


axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';


axios.interceptors.request.use(    
    config => {

        token && (config.headers.Authorization = token);        
        return config;    
    },    
    error => {        
        return Promise.error(error);    
    })

axios.interceptors.response.use(    
    response => {        
        if (response.status === 200) {            
            return Promise.resolve(response);        
        } else {            
            return Promise.reject(response);        
        }    
    },
    error => {        
        if (error.response.status) {            
            switch (error.response.status) {                
                case 401:                    
                    router.replace({                        
                        path: '/login',                        
                        query: { redirect: router.currentRoute.fullPath } 
                    });
                    break;
                case 403:                     
                    Toast({                        
                        message: 'Login expired, please login again',                        
                        duration: 1000,                        
                        forbidClick: true                    
                    });                    
                    localStorage.removeItem('token');                    
                    store.commit('loginSuccess', null);                    
                    setTimeout(() => {                        
                        router.replace({                            
                            path: '/login',                            
                            query: { 
                                redirect: router.currentRoute.fullPath 
                            }                        
                        });                    
                    }, 1000);                    
                    break; 
                case 404:                    
                    Toast({                        
                        message: 'Network request does not exist',                        
                        duration: 1500,                        
                        forbidClick: true                    
                    });                    
                break;                
                default:                    
                    Toast({                        
                        message: error.response.data.message,                        
                        duration: 1500,                        
                        forbidClick: true                    
                    });            
            }            
            return Promise.reject(error.response);        
        }       
    }
);
/** 
 * get function
 * @param {String} url 
 * @param {Object} params
 */
export function get(url, params){    
    return new Promise((resolve, reject) =>{        
        axios.get(url, {            
            params: params        
        })        
        .then(res => {            
            resolve(res.data);        
        })        
        .catch(err => {            
            reject(err.data)        
        })    
    });
}
/** 
 * post function
 * @param {String} url 
 * @param {Object} params 
 */
export function post(url, params) {    
    return new Promise((resolve, reject) => {         
        axios.post(url, QS.stringify(params))        
        .then(res => {            
            resolve(res.data);        
        })        
        .catch(err => {            
            reject(err.data)        
        })    
    });
}

By hbb

Leave a Reply

Your email address will not be published. Required fields are marked *