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 3retryCondition
: a function that determines whether to retry if an error occurs. The default is5xx
HTTP 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 intimeout
In the endretryDelay
The 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-retry
It will be in axios configaxios-retry
Field to hold the number of current retries (retryCount
)- Axios throws an error in the case of an HTTP exception/network exception.
axios-retry
Registers the error handler in the response interceptor and executesretryCondition
Determine whether a retry is required. If you need to retryretryCount
Do 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 (retryCondition
returnfalse
Reject 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.
- to
axios
Config 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.reject
Throw 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-retry
theretryCondition
Return 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