What is axios? What is axios? What is axios

Why do I need to request a retry

In the project, there will often be a lot of users’ network leakage or a variety of reasons caused by the occasional network exception request error, if there is no retry mechanism, sometimes the experience will be worse. At this time, the implementation of network error request error retry can also better solve this kind of contingency scenario.

How do you do that

We can use the axios-Retry library to implement the pickup. It’s very simple to use

import axiosRetry from 'axios-retry';
axiosRetry(axios, {});
Copy the code

Simply execute axiosRetry and pass the AXIOS instance. It also supports several configuration parameters

  • retries: Number of retries. The default value is 3
  • retryCondition: a function that determines whether to retry if an error occurs. The default is5xxHTTP errors or network exceptions or idemidemous requests (GET/HEAD/ OPTIONS/PUT/DELETE) will be retried.
  • shouldResetTimeout: Specifies whether to reset the timeout period during retry. The default is not reset. That is, multiple retry requests must be intimeoutIn the end
  • retryDelayThe retry delay between each request, which defaults to 0

For example, if I want to customize, retry 4 times, retry in addition to the default, 404 also retry, reset the timeout, retry delay 50ms, then this is ok

import axiosRetry from 'axios-retry';
axiosRetry(axios, {
    retries: 4.retryCondition: (err) = > axiosRetry.isNetworkOrIdempotentRequestError(err) || error.response.status === 404.shouldResetTimeout: true.retryDelay: 50
});
Copy the code

Realize the principle of

Axios-retry also implements a simple principle of retry

  • axios-retryIt will be in axios configaxios-retryField to hold the number of current retries (retryCount)
  • Axios throws an error in the case of an HTTP exception/network exception.axios-retryRegisters the error handler in the response interceptor and executesretryConditionDetermine whether a retry is required. If you need to retryretryCountDo the ++ operation, and then return a Prommise to re-initiate a new request using the current confignew Promise(resolve => setTimeout(() => resolve(axios(config)), delay));. If no retry is currently required (retryConditionreturnfalseReject the error object if the number of retries has been exceeded.)
  axios.interceptors.response.use(null.error= > {
    const config = error.config;
    / /...
    const currentState = getCurrentState(config);
    const shouldRetry = retryCondition(error) && currentState.retryCount < retries;

    if (shouldRetry) {
      currentState.retryCount += 1;
        / /...

      return new Promise(resolve= > setTimeout(() = > resolve(axios(config)), delay));
    }

    return Promise.reject(error);
  });
Copy the code

The detailed code is here. It’s very clear and easy to understand

further

In a real world scenario, many times the success of an HTTP request does not mean that our request is as expected. There are several scenarios in which a reload cannot be triggered using Axios-Retry directly

  • Service code exception

Take the author’s actual project as an example. When the back end returns an exception, HTTP code is 200, but code is not 0, such as {code:1, MSG :’some err’}. There may be occasional errors, which may also require retries

  • The asynchronous interface returned incorrectly

Assume the following scenario. First operation A uploads the video; Immediately after the operation B to query the information of this video, it may have just uploaded, and there is a delay when some back-end information falls into db. Occasionally, we may not find this information when we query it immediately, so we need to delay a few ms to find it. For example, {code:0,data:null} if code:0,data:’some thing’ is returned. Retry is also important at this point.

How to Retry gracefully

The axios-retry principle is implemented by responding to the interceptor’s error handler. Is it ok to throw this error in the interceptor’s normal handler? Of course you can.

  • toaxiosConfig and a custom option function to determine whether a retry is required
  • Call the judgment function in the response interceptor, set a flag bit if retry is required,Promise.rejectThrow an error
  instance.interceptors.response.use((response) = > {
    const { data, config, request } = response

    if(config? .[namespace]? .shouldRetry? .(data)) { config[namespace].needRetry =true
      return Promise.reject(
        createError(
          `Axios retry enhance error`,
          config,
          null,
          request,
          response
        )
      )
    }
    return response
  })
Copy the code
  • axios-retrytheretryConditionReturn true on the property read from the previous step and retry using axios-Retry
axiosRetry(instance, { ... config,retryCondition: (error) = > {
      const {
        retryCondition = axiosRetry.isNetworkOrIdempotentRequestError,
      } = config
      returnretryCondition(error) || error.config? .[namespace]? .needRetry }, })Copy the code

Thus, the code only needs to be called as follows

client.get<Result>('http://example.com/test', {
  retry: {
    // The request will retry when the code isn't 0 even the http code is 200
    shouldRetry: (res: Result) = >res.code ! = =0,}})Copy the code

encapsulation

Based on the above discussion, axios-Retry-enhancer is implemented by repackaging axios-Retry. Supports the original axios-retry parameters, with additional support for the defined retry logic mentioned above. Use the following to achieve elegant business retry

import axiosRetryEnhancer from 'axios-retry-enhancer'
import axios from 'axios'

const client = axios.create()
axiosRetryEnhancer(client, {
  // same options with axios-retry. See https://github.com/softonic/axios-retry#options
})

interface Result<T = unknown> {
  code: number
  data: T
}

client.get<Result>('http://example.com/test', {
  retry: {
    // The request will retry when the code isn't 0 even the http code is 200
    shouldRetry: (res: Result) = >res.code ! = =0,}})Copy the code

Code word is not easy, your praise is my biggest motivation, hey hey