[axios source code] - study and analysis of the request distribution function DispatchRequest

Welcome to my official account, "front-end wall".

1, Environmental preparation

  • axios version v0 twenty-four

  • Through github1s web page, you can see axios - dispatchRequest.js source code

  • clone to local is required for debugging

git clone https://github.com/axios/axios.git

cd axios

npm start

http://localhost:3000/

2, Function study

1. Overview of auxiliary functions

requestDispatch refers to the cancellation request Cancel Module, instantiation configuration module defaults Tools and functions utils And date conversion function transformData. The first three parts have been analyzed in the previous article and will not be repeated here.

"use strict";

var utils = require("./../utils");
var transformData = require("./transformData");
var isCancel = require("../cancel/isCancel");
var defaults = require("../defaults");
var Cancel = require("../cancel/Cancel");

2. Auxiliary function transformData

Transform the data for a request or a response
The Data in the result will be requested or returned

"use strict";

var utils = require("./../utils");
var defaults = require("./../defaults");

/**
 * @param {Object|String} data The data to be transformed
 * @param {Array} headers The headers for the request or response
 * @param {Array|Function} fns A single function or Array of functions
 * @returns {*} The resulting transformed data
 */
module.exports = function transformData(data, headers, fns) {
    var context = this || defaults;
    /*eslint no-param-reassign:0*/
    utils.forEach(fns, function transform(fn) {
        data = fn.call(context, data, headers);
    });

    return data;
};

===>Call location
config.data = transformData.call(
    config,
    config.data,
    config.headers,
    config.transformRequest
);

===>config.transformRequest Configuration location default.js
 transformResponse: [
    function transformResponse(data) {
        ...
        if (
            strictJSONParsing ||
            (forcedJSONParsing && utils.isString(data) && data.length)
        ) {
            try {
                return JSON.parse(data);
            } catch (e) {
                ...
            }
        }
        return data;
    },
],
  • Declare the global variable context to get the global context from the current context this or instance defaults
  • Call forEach in utils, and each function fn in fns will be triggered by callback to execute its internal logic. The input parameters of each FN are data and headers
  • From the perspective of context, it is actually JSON Parse () processed the data, but the headers were not used

Tips: this piece needs to be viewed in combination with the context. Otherwise, from the perspective of naming and function analysis, it is a tool function for processing dates, but what is the specific processing logic? Where will it be handled? I don't know. It's also a difficult place to read the source code, so we must contact the context.

3. Internal function throwIfCancellationRequested

Throws a Cancel if cancellation has been requested

If the cancellation request has been executed, a Cancel object is thrown

function throwIfCancellationRequested(config) {
    if (config.cancelToken) {
        config.cancelToken.throwIfRequested();
    }

    if (config.signal && config.signal.aborted) {
        throw new Cancel("canceled");
    }
}
  • The first one is to judge whether the cancelToken is instantiated. If so, execute the throwIfRequested method of the instance through Last article We know that cancelToken is a publish subscribe function. Once instantiated, the internal subscriber event Cancel will be executed immediately. If it is cancelled for the first time, a Cancel instance will be returned through resolvePromise
  • The second judgment is for fetch API This has not been reflected in the document, but it can be found in axios-README-line740 See usage example

4. Distribution function dispatchRequest

Dispatch a request to the server using the configured adapter

Send the request to the server with the configured adapter

/**
 * @param {object} config The config that is to be used for the request
 * @returns {Promise} The Promise to be fulfilled
 */
module.exports = function dispatchRequest(config) {
    throwIfCancellationRequested(config);

    // Ensure headers exist
    config.headers = config.headers || {};

    // Transform request data
    config.data = transformData.call(
        config,
        config.data,
        config.headers,
        config.transformRequest
    );

    // Flatten headers
    config.headers = utils.merge(
        config.headers.common || {},
        config.headers[config.method] || {},
        config.headers
    );

    utils.forEach(
        ["delete", "get", "head", "post", "put", "patch", "common"],
        function cleanHeaderConfig(method) {
            delete config.headers[method];
        }
    );

    var adapter = config.adapter || defaults.adapter;

    return adapter(config).then(
        function onAdapterResolution(response) {
            throwIfCancellationRequested(config);

            // Transform response data
            response.data = transformData.call(
                config,
                response.data,
                response.headers,
                config.transformResponse
            );

            return response;
        },
        function onAdapterRejection(reason) {
            if (!isCancel(reason)) {
                throwIfCancellationRequested(config);

                // Transform response data
                if (reason && reason.response) {
                    reason.response.data = transformData.call(
                        config,
                        reason.response.data,
                        reason.response.headers,
                        config.transformResponse
                    );
                }
            }

            return Promise.reject(reason);
        }
    );
};
  • Call throwIfCancellationRequested. If the user cancels the request on his own initiative, he will directly resolve or reject, and no subsequent logic will be executed

  • call transformData to convert the date format in the request header call to pass the current context config

  • Call the merge function in utils to flatten the header object information (which can be understood by the flat method of array in ES6)

  • Call the forEach function in utils. Every time you traverse a given array element, you will trigger the cleanHeaderConfig method, which will delete the redundant merged headers configuration

  • Define the global adapter to accept the adapter of the current instance

  • Return the execution result of the adapter. Because the asynchronous request is sent in the adapter, it needs to be called in a chain Get the return value in then(), and in this process, you need to do some processing on the resolved or reject value. The processing logic is in onAdapterResolution and onAdapterRejection respectively

  • throwIfCancellationRequested is called in onAdapterResolution and onAdapterRejection to detect whether the user triggered the cancellation request at this time. So there's a problem - the requests have been sent, and even the results have been returned. Why do you do this again? Answer: in order not to execute subsequent logic, performance can be improved.

Tips: for the flattening of arrays, please refer to Teacher Ruan Yifeng's -es6 introduction

Tips: you don't need to tangle too much about the concept of adapter. Later articles will deeply analyze the adapters of [Browser, node]

3, Summary

  the logic of the request distribution module is relatively simple, and the complexity may lie in the calling and undertaking context of throwIfCancellationRequested. throwIfCancellationRequested personal understanding is one of the exits when the user actively cancels the request. The execution time point of this exit is when the request has been sent, has not responded or has responded. Compared with the previous cancel module, the exit there is in the executor of the executor. When the ajax request of the client and the repeated request before or after the http establishment of the node are completed, the execution time will be earlier or later than the exit in the current DispatchRequest.

4, Reference

1. Articles of xianlingge Detailed Axios source code interpretation

2. Lin Jingyi's article Lin Jingyi's Notepad - Axios source code analysis (V): core tools and methods

3. Ruokawa's article Learn the overall architecture of axios source code and build your own request library

4. Jieling's article In depth interpretation of axios source code

Keywords: Javascript Front-end axios Vue.js source code

Added by zako234 on Wed, 16 Feb 2022 03:17:41 +0200