Send a person rose, hand has lingering fragrance, what are you, what is your world 💡

preface

This article takes a look at some of the encapsulation and application of AXIOS in the project. Interested developers are welcome to read this article.

Install dependencies

  • Axios installation
    # yarn | NPM installation
    yarn add axios | npm install axios
Copy the code
  • Axios use
import axios from "axios";

axios.post("url",{}).then((res) = > {
  // The interface called successfully
}).catch((error) = > {
  // Interface call failure destroyed
});

/* Support all HTTP requests, request cancellation, concurrent requests, etc. For more details and how to use the official documentation: [AXIos documentation](http://www.axios-js.com/zh-cn/docs/) */
Copy the code

Configuration axios

Let’s get back to the focus of this article, how to properly configure it to improve development efficiency and maintainability.

  • To create the configuration file, we’re just wrapping axios a little bit, so create the config folder under SRC and the axios.js file under config

  • The wrapped AXIOS configuration code is as follows. Place the following code in the axios.js file.

/** * Encapsulate AXIos slightly * 1. Set request timeout * 2. Add a request interceptor and add token * to the header of each request. 3. Add a response interceptor and return */ based on the server return status
"use strict";
import axiosObj from "axios";
// To import the VUEX, you need to obtain the token stored in it. If you do not need the token, you do not need to import the vuex
import store from ".. /store";
const defaultConfig = {
 // baseURL is omitted here. Considering that the project may be developed by many people and the domain name may be different, the domain name is configured in base.js separately by pulling out the API

 // Request timeout
 timeout: 60 * 1000.// Whether credentials are required for cross-domain requests
 // withCredentials: true, // Check cross-site Access-Control
 heards: {
   get: {
     // Set the default request header. When a special request header is needed, pass it as a parameter to override the default parameter
     "Content-Type": "application/x-www-form-urlencoded; charset=utf-8"
   },
   post: {
     // Set the default request header. When a special request header is needed, pass it as a parameter to override the default parameter (config).
     / / such as:
     // services.post(`${base.lkBaseURL}/uploads/singleFileUpload`, file, {
     // headers: { "Content-Type": "multipart/form-data" }
     / /});
     "Content-Type": "application/json; charset=utf-8"}}// The data is processed before the request is sent to the server and axios serializes the data by default
 // transformRequest:[function(data){
 //
 // }],
 // Modify the response data before passing it to then/catch
 // transformResponse:[function(data){
 //
 // }]
 };
/** * Request failure after the unified processing, of course, there are more status code judgment, according to your business needs to expand *@param Status Indicates the status code * of the failed request@param MSG Error message */
const errorHandle = (status: number, msg: string) = > {
 // Determine the status code
 switch (status) {
   // 401: Login page is displayed
   case 401:
     // Jump to the login page
     break;
   // 403 Token expired
   case 403:
     // If you do not need to refresh the tokens automatically, you can remove the tokens from the local storage to switch to the login page

     break;
   // 404 request does not exist
   case 404:
     // The resource does not exist
     break;
   default:
     console.log(msg); }};// Create an instance
const _axios = axiosObj.create(defaultConfig);
// Request interceptor
_axios.interceptors.request.use(
 function(config) {
   // Get the token from vuex
   const token = store.state.token;
   // If the token exists, add it to the request header
   token && (config.headers.token = token);
   return config;
 },
 function(error) {
   // Do something with request error
   error.data = {};
   error.data.msg = "Server exception";
   return Promise.reject(error); });// Response interceptor
_axios.interceptors.response.use(
 function(response) {
   // Clear the tokens in the local storage. If you need to refresh the tokens, exchange the old tokens with the server and add the new tokens to the VUEX
   if(response.data? .code ===401) {
     localStorage.removeItem("token");
     // Page refresh
     parent.location.reload();
   }
   if (response.status === 200) {
     // Process data in the interface
     if(response.data? .data) {try {
         const dataObj = JSON.parse(response.data.data);
         if (typeof dataObj == "object" && dataObj) {
           // Convert a JSON string to a JSON objectresponse.data.data = dataObj; }}catch (e) {
         // If it is not a JSON string, it is not processed
         returnresponse.data; }}return response.data;
   }
   response.data.code = -1;
   response.data.msg = "Server error";
   return response;
 },
 function(error) {
    if (error) {
      // The request has been sent, but not in 2xx
      errorHandle(error.status, error.data.msg);
      return Promise.reject(error);
    } else {
      / / broken network
      return Promise.reject(error); }});export default _axios;
Copy the code

Now that the core configuration of AXIos is complete, let’s take a look at what the configuration does.

  • Setting timeout
  • Centralized configuration of request headers
  • If the response fails, the status code is processed uniformly
  • Add tokens to request interception
  • Token expiration and returned data are processed accordingly in response interception
  • Description The interface domain name is removed
  • And then finally we export that, which we’ll use when we pull out of the API

Separate API and domain name interface

Why do I do API extraction? If we write this.$axios.get() in the business code for all of our requests, we will have to go to the business code one by one to find and modify the request. There is no maintenance at all. Next we will take you to implement API separation 😃

Implementation approach

We will improve the maintainability of the project interface by following several steps:

  1. Create an interface module file, write the interface address, parameters, and request mode in the file, and export the file for reference in the API unified export file.
  2. Create the interface domain name file. There may be multiple interface domain names in the team. We will write them here and export them for reference in the interface module file.
  3. Create a unified API exit file and divide the API interface into multiple modules based on function (Step 1), which is convenient for multi-person development. Appoint the module leader in the team, introduce all modules here, expose references, and then mount the Vue prototype both through this.$API. Module name. Method name for reference.

The implementation code

  • Create the API folder under SRC
  • Create an interface domain name fileindex.js
    /* * interface domain name management * * */
   const base = {
       lk:"https://www.kaisir.cn/user".other:"https://kf.kaisir.cn/api"
   };
   
   export default base;
Copy the code
  • inapiCreate an interface module file in the folder named as follows:Module name + API.
    /* * webmaster * */
    import services from '.. /plugins/axios'
    import base from './base'; // Import the interface domain name list
    const websiteManageAPI = {
        / / login
        login(params){
            return services._axios.post(`${base.lk}/login`,params);
        },
        // Test the POST interface
        postJSON(params){
            return services._axios.post(`${base.lk}/getter/postJSON`,params);
        },
        // Test the GET interface
        getJSON(pageNo,pageSize){
            return services._axios.get(`${base.lk}/getter/getJSON`, {params: {pageNo:pageNo,pageSize:pageSize}}); }};export default websiteManageAPI;
Copy the code
  • Create an API unified export file
   /** * API unified exit ** /
   // Site management interface
   import websiteManageAPI from './websiteManageAPI';
   // Other module interfaces
   
   // Export interface
   export default {
       websiteManageAPI,
       // ...
   }
Copy the code

After completing the above steps, the contents of the API folder should look like the following.

Next, we can choose to mount what is exposed by the API unified exit file to the prototype. Or choose load on demand and import whichever module is used in the business code.

Here’s how to mount it to the prototype by adding the following code to the entry file mian.js.

// Mount to the prototype (main.js)
Vue.prototype.$api = api;
Copy the code

Adapter Vue3

When used in Vue3, the idea of body encapsulation is the same. If the project uses TypeScript, there will be a type declaration in the AXIos configuration file. If you need to mount the API to the prototype, you will need to declare the API type in the declaration file. In the main. Js mount writing need to app. Config. GlobalProperties. = $API API; .

On October 20, 2020, I reconstructed the previous project with Vue3. The axios configuration code address for Vue3 is as follows:

API folder: SRC/API

Axios configuration file: config/axios.ts

Vue type declaration file: SRC /shims-vue.d.ts

Developers interested in refactoring the Vue2 project with Vue3 can take a step further: Refactoring the Vue2 project with Vue3

The practical application

For example, all back-end interfaces need to be logged in to and accessed based on the token returned after successful login. Back-end interfaces use ShirO + JWT to implement interface authentication and token provisioning

  • When the page loads, the token is obtained from the local store
    // app. vue,created lifecycle
    const token = localStorage.getItem("token");
Copy the code
  • Check whether the token exists and obtain it if it does not
    // 
    if(lodash.isEmpty(token)){
        // Login page: This step is only used for demonstration purposes. The user name and password are fixed data
        const userInfo = {
          "username":"Test"."password":"0x89oikklsa"
        };
        // Call the login API
        this.$api.websiteManageAPI.login(userInfo).then((res) = >{
          // Store the token and update it to the vuEX
          localStorage.setItem("token",res.token);
          this.$store.state.token = res.token;
        });
    }else{
        // Update the tokens in vuEX
        this.$store.state.token = token;
    }
Copy the code
  • The execution result
  • Call other interfaces to test whether the request header token is added successfully
    // Test whether other interfaces can be called successfully
    this.$api.websiteManageAPI.getJSON(1.3).then((res) = >{
        console.log("Interface call successful");
        console.log(res)
    });
}
Copy the code
  • The execution result

Write in the last

  • If there are any errors in this article, please correct them in the comments section. If this article helped you, please like it and follow 😊
  • This article was first published in the Nuggets. If you need to reprint it, please leave a comment at 💌