Home  >  Article  >  Web Front-end  >  Parse the encapsulation request of axios in vue (with step code)

Parse the encapsulation request of axios in vue (with step code)

藏色散人
藏色散人forward
2022-08-10 10:05:541774browse

1. Introduction

axios is a lightweight HTTP client that performs HTTP requests based on the XMLHttpRequest service, supports rich configuration, supports Promise, and supports browsing Server side and Node.js side. Since Vue2.0, Youda announced that it will cancel the official recommendation of vue-resource and recommend axios instead. Now axios has become the first choice for most Vue developers. (If you are not familiar with axios, you can view its API here.) [Related recommendations: vue.js video tutorial]

Before encapsulating, let’s take a look at it first, without encapsulation In this case, what an axios request looks like in an actual project.

It probably looks like this:

axios('http://localhost:3000/data', {
  method: 'GET',
  timeout: 1000,
  withCredentials: true,
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'xxx',
  },
  transformRequest: [function (data, headers) {
    return data;
  }],
  // 其他请求配置...
})
.then((data) => {
  // todo: 真正业务逻辑代码
  console.log(data);
}, (err) => {
  if (err.response.status === 401) {
  // handle authorization error
  }
  if (err.response.status === 403) {
  // handle server forbidden error
  }
  // 其他错误处理.....
  console.log(err);
});

You can see that in this code, the page code logic is only on line 15, and a large block of request configuration above The code and a large chunk of response error handling code below have almost nothing to do with the page function, and these contents are similar in every request, and some parts are even exactly the same.

2. After encapsulation

1. Encapsulation steps

The essence of encapsulation is to add various things outside the content to be encapsulated, and then put them It is presented to users as a new whole to achieve expansion and ease of use.

Encapsulationaxios What needs to be done is to configure the configuration common to all HTTP requests on axios in advance, reserve the necessary parameters and interfaces, and then use it as a new The axios returns.

The directory structure is as follows (generated by Vue-cli 3.0):

##|--public/

|--mock/
| |--db.json # My new interface simulation data
|--src/
| |--assets/
| |--components/
| |--router/
| |--store/
| |--views/
| |--Home.Vue
| |--App.vue
| |--main.js
| |--theme.styl
|--package.json
|...

2. Package target

on the Home page , making an axios request is as simple as calling a method with only a few parameters, so I can focus on the business code.

1. Encapsulate axios into a separate file

    Create the utils/http.js file under src
  •   cd src
      mkdir utils
      touch http.js
    Introducing axios
  •   // src/utils/http.js
      import axios from 'axios';
    Create a class
  •   //src/utils/http.js
      //...
      class NewAxios {
      
      }
    Configure different request addresses for different environments
Configure different

baseURL according to process.env.NODE_ENV , so that the project can automatically switch the request host address in different environments by simply executing the corresponding packaging command.

// src/utils/http.js

//...
const getBaseUrl = (env) => {
  let base = {
    production: '/',
    development: 'http://localhost:3000',
    test: 'http://localhost:3001',
  }[env];
  if (!base) {
    base = '/';
  }
  return base;
};

class NewAxios {
  constructor() {
    this.baseURL = getBaseUrl(process.env.NODE_ENV);
  }
}

    Configuring the timeout

timeout attribute, I usually set it to 10 seconds.

// src/utils/http.js

//...
class NewAxios {
  constructor() {
    //...
    this.timeout = 10000;
  }
}

    Configuration to allow carrying credentials

widthCredentials property is set to true

// src/utils/http.js

//...
class NewAxios {
  constructor() {
    //...
    this.withCredentials = true;
  }
}

    Create a method request
on the instance of this class. In the

request method, create a new axios instance, receive the request configuration parameters, process the parameters, add configuration, and return the axios instance The request result (a promise object).

You can also directly use the default exported axios instance without creating it, and then put all configurations on it, but in this way the entire project will share one axios instance. Although this is sufficient for most projects, the request and response structures of different service addresses in some projects may be completely different. In this case, sharing one instance cannot support it. So in order to make the encapsulation more versatile and flexible, I will use the

create method of axios so that each request is a new axios instance.

// src/utils/http.js

//...
class NewAxios {
  //...
  request(options) {
    // 每次请求都会创建新的axios实例。
    const instance = axios.create();
    const config = { // 将用户传过来的参数与公共配置合并。
      ...options,
      baseURL: this.baseURL,
      timeout: this.timeout,
      withCredentials: this.withCredentials,
    };
    // 配置拦截器,支持根据不同url配置不同的拦截器。
    this.setInterceptors(instance, options.url);
    return instance(config); // 返回axios实例的执行结果
  }
}

Because the interceptor configuration content is relatively large, it is encapsulated into an internal function.

    Configuring the request interceptor
All modifications to the request parameters before sending the request are configured here. For example, uniformly add token credentials, uniformly set languages, uniformly set content types, specify data formats, etc. Remember to return this configuration after finishing, otherwise the entire request will not proceed.

I will configure a

token here.

// src/utils/http.js

//...
class NewAxios {
  //...
  // 这里的url可供你针对需要特殊处理的接口路径设置不同拦截器。
  setInterceptors = (instance, url) => { 
    instance.interceptors.request.use((config) => { // 请求拦截器
      // 配置token
      config.headers.AuthorizationToken = localStorage.getItem('AuthorizationToken') || '';
      return config;
    }, err => Promise.reject(err));
  }
  //...
}

    Configuring the response interceptor
Perform a round of pre-processing of the response data before the request's

then or catch processing deal with. For example, filtering response data, and more importantly, unified error processing for various response error codes, network disconnection processing, etc.

I will judge 403 and disconnection here.

// src/utils/http.js

//...
class NewAxios {
  //...
  setInterceptors = (instance, url) => {
    //...
    instance.interceptors.response.use((response) => { // 响应拦截器
      // todo: 想根据业务需要,对响应结果预先处理的,都放在这里
      console.log();
      return response;
    }, (err) => {
      if (err.response) { // 响应错误码处理
        switch (err.response.status) {
          case '403':
            // todo: handler server forbidden error
            break;
            // todo: handler other status code
          default:
            break;
        }
        return Promise.reject(err.response);
      }
      if (!window.navigator.online) { // 断网处理
        // todo: jump to offline page
        return -1;
      }
      return Promise.reject(err);
    });
  }
  //...
}

In addition, in the interceptor, it is also suitable to place buffering effects such as loading: Display loading in the request interceptor and remove loading in the response interceptor. In this way, all requests will have a unified loading effect.

    Export new instances by default
  •   // src/utils/http.js
      
      //...
      export default new NewAxios();

The final complete code is as follows:

// src/utils/http.js

import axios from 'axios';

const getBaseUrl = (env) => {
  let base = {
    production: '/',
    development: 'http://localhost:3000',
    test: 'http://localhost:3001',
  }[env];
  if (!base) {
    base = '/';
  }
  return base;
};

class NewAxios {
  constructor() {
    this.baseURL = getBaseUrl(process.env.NODE_ENV);
    this.timeout = 10000;
    this.withCredentials = true;
  }

  // 这里的url可供你针对需要特殊处理的接口路径设置不同拦截器。
  setInterceptors = (instance, url) => {
    instance.interceptors.request.use((config) => {
      // 在这里添加loading
      // 配置token
      config.headers.AuthorizationToken = localStorage.getItem('AuthorizationToken') || '';
      return config;
    }, err => Promise.reject(err));

    instance.interceptors.response.use((response) => {
      // 在这里移除loading
      // todo: 想根据业务需要,对响应结果预先处理的,都放在这里
      return response;
    }, (err) => {
      if (err.response) { // 响应错误码处理
        switch (err.response.status) {
          case '403':
            // todo: handler server forbidden error
            break;
            // todo: handler other status code
          default:
            break;
        }
        return Promise.reject(err.response);
      }
      if (!window.navigator.online) { // 断网处理
        // todo: jump to offline page
        return -1;
      }
      return Promise.reject(err);
    });
  }

  request(options) {
    // 每次请求都会创建新的axios实例。
    const instance = axios.create();
    const config = { // 将用户传过来的参数与公共配置合并。
      ...options,
      baseURL: this.baseURL,
      timeout: this.timeout,
      withCredentials: this.withCredentials,
    };
    // 配置拦截器,支持根据不同url配置不同的拦截器。
    this.setInterceptors(instance, options.url);
    return instance(config); // 返回axios实例的执行结果
  }
}

export default new NewAxios();

Now

axios Encapsulation is 80% complete. We still need to further combine axios with the interface and encapsulate it one layer further to achieve the encapsulation goal I set at the beginning.

3. Use the new axios packaging API

  • 在 src 目录下新建 api 文件夹。把所有涉及HTTP请求的接口统一集中到这个目录来管理。
  • 新建 home.js。我们需要把接口根据一定规则分好类,一类接口对应一个js文件。这个分类可以是按页面来划分,或者按模块等等。为了演示更直观,我这里就按页面来划分了。实际根据自己的需求来定。
  • 使用新的 axios 封装API(固定url的值,合并用户传过来的参数),然后命名导出这些函数。
// src/api/home.js 

import axios from '@/utils/http';
export const fetchData = options => axios.request({
  ...options,
  url: '/data',
});
export default {};

在 api 目录下新建 index.js,把其他文件的接口都在这个文件里汇总导出。

 // src/api/index.js
  
  export * from './home';

这层封装将我们的新的axios封装到了更简洁更语义化的接口方法中。

现在我们的目录结构长这样:

|--public/
|--mock/
|   |--db.json  # 接口模拟数据
|--src/
|   |--api/     # 所有的接口都集中在这个目录下
|       |--home.js  # Home页面里涉及到的接口封装在这里
|       |--index.js # 项目中所有接口调用的入口
|   |--assets/
|   |--components/
|   |--router/
|   |--store/
|   |--utils/
|       |--http.js  # axios封装在这里
|   |--views/
|       |--Home.Vue
|   |--App.vue
|   |--main.js
|   |--theme.styl
|--package.json
|...

4.使用封装后的axios

现在我们要发HTTP请求时,只需引入 api 下的 index.js 文件就可以调用任何接口了,并且用的是封装后的 axios。

// src/views/Home.vue

<template>
  <div class="home">
    <h1>This is home page</h1>
  </div>
</template>

<script>
// @ is an alias to /src
import { fetchData } from &#39;@/api/index&#39;;

export default {
  name: &#39;home&#39;,
  mounted() {
    fetchData()  // axios请求在这里
      .then((data) => {
        console.log(data);
      })
      .catch((err) => {
        console.log(err);
      });
  },
};
</script>

axios请求被封装在fetchData函数里,页面请求压根不需要出现任何axios API,悄无声息地发起请求获取响应,就像在调用一个简单的 Promise 函数一样轻松。并且在页面中只需专注处理业务功能,不用被其他事物干扰。

The above is the detailed content of Parse the encapsulation request of axios in vue (with step code). For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:jb51.net. If there is any infringement, please contact admin@php.cn delete