Read a lot of people’s encapsulating Axios tutorials online, but there are more or less inappropriate points, here are my best practices for you.

The interceptor does not return data, but still returns an AxiosResponse object

The articles on the Internet ask you to use interceptors to directly return data, which is actually very inappropriate, so that you will be difficult to expand the function.

Not recommended

import Axios from 'axios'

const client = Axios.create({
  // Your configuration
})

client.interceptors.response.use(response= > {
  // The Internet always asks you to return the data directly
  // This makes it difficult to support subsequent functions
  return response.data
})

export default client
Copy the code

Recommended practices

It is recommended to use functions instead of interceptors

import Axios, { AxiosRequestConfig } from 'axios'

const client = Axios.create({
  // Your configuration
})

export async function request(url: string, config? : AxiosRequestConfig) {
  const response = awaitclient.request({ url, ... config })const result = response.data
  // Your business judgment logic
  return result
}

export default client
Copy the code

At this point some people may say too much trouble, please wait a moment, continue to read.

Add an extension to your request

A lot of times, our development process looks like this:

Send request => get data => Render contentCopy the code

Unfortunately, this is an ideal situation, and there are special cases where you need to handle exceptions or additional support, such as:

  • When a request fails, you want to automatically retry the request for more than three times
  • In paging data, the automatic interruption of the previous request when a new one is made
  • When a third party provides a JSONP interface and you can only use static pages (PS: Axios does not support JSONP)
  • More and more

You can only write code support silently when sending the above scenarios, but if you don’t intercept the Axios response, you can use the solution provided by the open source community.

Support request retry

Install AXIos-Retry to enable automatic retry in your AXIos

import Axios, { AxiosRequestConfig } from 'axios'
import axiosRetry from 'axios-retry'

const client = Axios.create({
  // Your configuration
})

// Install the Retry plug-in
// When a request fails, the request is automatically rerequested
axiosRetry(client, { retries: 3 })

export async function request(url: string, config? : AxiosRequestConfig) {
  const response = awaitclient.request({ url, ... config })const result = response.data
  // Your business judgment logic
  return result
}

// Only after three failures do you really fail
const data = request('http://example.com/test')
Copy the code

The PS: AXIos-Retry plug-in supports configuring a single request

Support for JSONP requests

Install Axios-jSONp to make your AXIos support JSONP functionality.

import Axios, { AxiosRequestConfig } from 'axios'
import jsonpAdapter from 'axios-jsonp'

const client = Axios.create({
  // Your configuration
})

export async function request(url: string, config? : AxiosRequestConfig) {
  const response = awaitclient.request({ url, ... config })const result = response.data
  // Your business judgment logic
  return result
}

export function jsonp(url: string, config? : AxiosRequestConfig) {
  returnrequest(url, { ... config,adapter: jsonpAdapter })
}

// You can now send jSONP requests
const data = jsonp('http://example.com/test-jsonp')
Copy the code

Supports URI version control

Anyone with experience in Web API development will encounter a problem: if there is a major change to the API, how do you release the new API while keeping the old version available?

This situation is not uncommon in server-side development scenarios, especially for public apis such as douban API (invalid).

Currently, there are three main types of version control supported:

type describe
URI Versioning Version will be passed in the URI of the request (default)
Header Versioning The custom request header specifies the version
Media Type Versioning The Accept request header specifies the version

URI version control refers to the version passed in the request URI, such as https://example.com/v1/route and https://example.com/v2/route.

import Axios, { AxiosRequestConfig } from 'axios'

const client = Axios.create({
  // Your configuration
})

client.interceptors.request.use(config= > {
  // The simplest solution
  config.url = config.url.replace('{version}'.'v1')
  return config
})

// GET /api/v1/users
request('/api/{version}/users')
Copy the code

Header and Media Type modes can be implemented by referring to the following article

  • Implement the Web API Versioning function
  • nest versioning

Keep requests unique

In a background table page that supports page-turning, a user clicks the page-turning button and requests a waiting response. However, the user clicks search and needs to retrieve the data again.

  1. Page turn request first return, search data return, data display normal
  2. Search data is returned first, and page data is returned again. Data is displayed abnormally (usually in load balancing scenarios)

To do this, you want to be able to cancel the last request automatically, so you look at Axios’ cancel request, but you need it in a lot of places, so you can encapsulate it as a separate function.

import Axios from 'axios'

const CancelToken = Axios.CancelToken

export function withCancelToken(fetcher) {
  let abort

  function send(data, config) {
    cancel() // Cancel

    const cancelToken = new CancelToken(cancel= > (abort = cancel))
    returnfetcher(data, { ... config, cancelToken }) }function cancel(message = 'abort') {
    if (abort) {
      abort(message)
      abort = null}}return [send, cancel]
}
Copy the code

use

function getUser(id: string, config? : AxiosRequestConfig) {
  return request(`api/user/${id}`, config)
}

// Wrap the request function
const [fetchUser, abortRequest] = withCancelToken(getUser)

// Send the request
// If the last request does not come back, it will be automatically cancelled
fetchUser('1000')

// Usually no active invocation is required
// But can be called during the component destruction lifecycle
abortRequest()
Copy the code

This does not need to automatically cancel the time, directly use the original function can, also will not affect the use of the original function

After the language

There’s a lot more that Axios encapsulation can do, such as global error handling (which doesn’t affect normal requests), and encapsulation shouldn’t just use interceptors to return data directly.

In addition, request modules should be kept separate. It is recommended to extend AxiosRequestConfig or make a separate function available for external calls to make it a separate HTTP module.