SoFunction
Updated on 2025-04-10

How to implement axios custom adapter adapter

1. Functions to be implemented by the adapter

When we implement additional data modules based on axios, we should align with the axios pattern. Therefore, in the returned data format, the implemented functions should be kept as consistent as possible.

1.1 promises and tools

All adaptations should be implemented in Promise.

Moreover, some functions are implemented by axios to implement them by itself, for example

  • Splicing of url: that is, splicing of baseURL and url. If baseURL exists and url is a relative path, splicing is performed, otherwise url will be used directly;
  • Parameter splicing: If it is a get request, you need to splice the object type into the format of the url parameter and complete the splicing with the url;

These are two basic tools and methods that you need to implement.

1.2 Response format

Here we need to notice the normal and abnormal format of the request interface.

When the interface is normal:

const result = {
    status: 200, // http status of the interface    statusText: 'ok',
    config: 'config', // The incoming config configuration can be returned as it is, making it easy to use in response interceptors and response results    data: {}, //Real interface returns result};

When the interface is abnormal, we can see the processing of error information in the axios source code createError, enhanceError (enhanceError is called in createError). First, an error instance will be created, and then an attribute will be added to this error instance:

 = function enhanceError(error, config, code, request, response) {
     = config;
    if (code) {
         = code;
    }

     = request;
     = response;
     = true;

     = function toJSON() {
        return {
            // Standard
            message: ,
            name: ,
            // Microsoft
            description: ,
            number: ,
            // Mozilla
            fileName: ,
            lineNumber: ,
            columnNumber: ,
            stack: ,
            // Axios
            config: ,
            code: ,
        };
    };
    return error;
};

As you can see, in addition to normal error messages, many other attributes are also added, such as request, response, config, etc. Here, when we implement the adapter ourselves, it is best to write it in this way, so as to facilitate unified processing of the higher-level business layer and avoid special processing for separate adapters.

Regarding the content in 1.1 and 1.2, if you do not compile it, you need to implement it yourself. If you want to compile it through packaging tools such as webpack, you can directly refer to the methods in axios without implementing them yourself. Please refer to the official mock-axios implemented based on axios. For example:

import axios from 'axios';
import buildURL from 'axios/lib/helpers/buildURL';
import isURLSameOrigin from 'axios/lib/helpers/isURLSameOrigin';
import btoa from 'axios/lib/helpers/btoa';
import cookies from 'axios/lib/helpers/cookies';
import settle from 'axios/lib/core/settle';
import createError from 'axios/lib/core/createError';

Then use it directly, no need to do secondary development.

1.3 Timeout setting

We cannot wait for the response of third-party services infinitely. If the third-party services are unresponsive or the response time is too long, they should be terminated in a timely manner. In axios, the front-end uses XMLHttpRequest and http on the node side to implement interface requests. Both have timeout settings. You can set the timeout field to set the timeout time and automatically cancel the current request.

For example, some requests initiated do not have a timeout setting. For example, jsonp is a request initiated by creating a script tag. This request must be terminated until the server responds (success or failure). At this time, we need to use a setTimeout to simulate it ourselves, but in this way, even if we return to the business layer and say "Timeout, the current request has been cancelled", the request is actually still there, but if the specified time exceeds the specified time, the corresponding successful operation will no longer be performed.

1.4 Actively cancel the request

We will also have many scenarios where we need to actively cancel the current request without the timeout, such as switching the route before the request returns; before the last request responds, we need to issue a new request, etc. All need to actively cancel the current request.

Axios has provided the function of canceling the request, we only need to access according to the rules. Let's take a look at how to cancel the request in the XMLHttpRequest requester, which can also be used as appropriate when writing a custom requester.

In lib/adapters/#L158:

// If cancelToken is already configured in configif () {
    // Handle cancellation
    // If the method to cancel the request is executed in the outer city, the current request will be cancelled here    (function onCanceled(cancel) {
        if (!request) {
            return;
        }

        // Use the abort method to cancel the current request in xhr        ();
        reject(cancel);
        // Clean up request
        request = null;
    });
}

When writing our own adapter, we can also copy this paragraph and replace the internal cancellation operation with our own.

At this point, if all the above functions are implemented, a standard adapter has been completed.

2. Write a custom adapter

The adapters that everyone needs must be different and the complexity is also different. For example, some people want to access the requests of mini programs, and I want to access the data request methods provided in the client. We are just explaining the implementation method by implementing a simple jsonp adapter.

We develop in the es6 module. All implementations are explained in the code.

// The config here is all the configurations in axiosconst jsonpAdapter = (config) => {
    return new Promise((resolve, reject) => {
        // Whether the current operation has been cancelled        // Because jsonp does not have a way to cancel the request actively        // IsAbort is used here to identify        let isAbort = false;

        // Timer identifier        let timer = null;

        // The name of the execution method,        const callbackName = `jsonp${()}_${()
            .toString()
            .slice(2)}`;

        // Here it is assumed that the splicing method of baseURL and url has been implemented        const fullPath = buildFullPath(, );

        // Here it is assumed that the url and parameter splicing method has been implemented        // What's different is that jsonp needs to insert an additional callback method        const url = buildURL(
            fullPath,
            {
                ...,
                ...{ [ || 'callback']: callbackName },
            },
            
        );

        // Create a script tag        let script = ('script');

        // After successful execution        function remove() {
            if (script) {
                 =  = null;

                // Remove script tag                if () {
                    (script);
                }
                // Cancel the timer                if (timer) {
                    clearTimeout(timer);
                }

                script = null;
            }
        }

        // After successful request        window[callbackName] = (data) => {
            // If a request is required, no more execution            if (isAbort) {
                return;
            }

            // Return format            const response = {
                status: 200,
                statusText: 'ok',
                config,
                request: script,
                data: data,
            };
            remove();
            // In fact, a set operation here will additionally determine whether it is a reasonable status            // If it is reasonable for us to set 404 in it, we will also enter the resolve state            // But we won't implement this here            // settle(resolve, reject, response);
            resolve(response);
        };

        // Request failed         = function (error) {
            remove();

            reject(createError('Network Error', config, 404));
        };

        // If the timeout time is set        if () {
            timer = setTimeout(function () {
                remove();
                // Cancel the current operation                isAbort = true;
                reject(
                    createError(
                        'timeout of ' +  + 'ms exceeded',
                        config,
                        405
                    )
                );
            }, );
        }

        // If a cancel operation is defined        if () {
            (function () {
                if (!script) {
                    return;
                }
                remove();
                isAbort = true;

                reject(createError('Cancel Error', config, 404));
            });
        }

         = url;
        const target =
            ('script')[0] || ;
         && (script, target);
    });
};

export default jsonpAdapter;

3. Add the adapter to axios

axios' config provides the adapter field for us to insert our own adapter. There are two situations when using a custom adapter:

1. Use only custom adapters;

2. Use a custom adapter in some cases, and use axios' own adapter in other cases.

The first situation is fine, you only need to return the result returned by your adapter; and in the second situation, there is a small hole that needs to be stepped on, so we will only explain the second situation here. I want to add the jsonp adapter I just implemented to axios, and only call the adapter when the parameter has format=jsonp, and the other ones are used to use the adapter provided by axios.

import Axios from 'axios';
import jsonpAdapter from './jsonpAdater';

const request = ({
    adapter: (config) => {
        if (config?.params?.format === 'jsonp') {
            return jsonpAdapter(config);
        }

        // This needs to be set to empty        // Otherwise, it will cause an infinite loop        return defaultAxios({ ...config, ...{ adapter: undefined } });
    },
});

Make a request with a custom adapter jsonp.

// Make a request with custom adapter jsonpvar options = {
    params: {
        format: 'jsonp',
    },
};
request(
    '/v1/newsapp/answer/share/oneQ?qID=506336',
    options
)
    .then(function (response) {
        ('jsonp response', response);
    })
    .catch(function (error) {
        ('jsonp error', error);
    });

Use the default axios adapter to initiate a request.

// Use the default axios adapter to initiate a requestrequest('/v1/newsapp/answer/share/oneQ?qID=506336')
    .then(function (response) {
        ('axios response', response);
    })
    .catch(function (error) {
        ('axios error', error);
    });

4. Summary

Here, we have implemented a custom adapter, which can be triggered when certain conditions are met. Through this idea, we can also implement a custom mock method. For example, when the parameter contains format=mock, the mock interface will be called, otherwise the request will be normal.

The above is the detailed content of how to implement axios custom adapter adapter. For more information about axios custom adapter adapter, please follow my other related articles!