“This is the seventh day of my participation in the First Challenge 2022.

First in my blog – big front-end engineer growth route – [AXIos source] – request distribution function DispatchRequest parsing

First, environmental preparation

  • Axios version v0.24.0

  • The source code of axios-dispatchRequest.js can be viewed from github1s

  • The debugging needs to be clone to the local PC

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

cd axios

npm start

http://localhost:3000/
Copy the code

Second, function study

1. Overview of auxiliary functions

RequestDispatch references the Cancel request Cancel module, the instantiation configuration module defaults, the utility function utils, and the date conversion function transformData, the first three of which have been analyzed in the previous article and will not be described 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");
Copy the code

2. Auxiliary functionstransformData

Transform the data for a request or a response Will request or return data in the result

"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);
    });

    returndata; }; === config.data = transformdata. call(config, config.data, config.headers, config.transformRequest); === config.transformRequest configuration locationdefault.js
 transformResponse: [
    function transformResponse(data) {...if (
            strictJSONParsing ||
            (forcedJSONParsing && utils.isString(data) && data.length)
        ) {
            try {
                return JSON.parse(data);
            } catch(e) { ... }}returndata; },].Copy the code
  • Declare global variablescontextFrom the current contextthisOr instancedefaultsGetting the global context
  • callutilsIn theforEach.fnsEach of the functions infnIs triggered by a callback to execute its internal logic, eachfnAll of the entries aredataandheaders
  • In the context ofJSON.parse()Took care of itdata.headersI didn’t use it

Tips: This section needs to be viewed in context, otherwise it is a tool function for handling dates from the naming and functional analysis, but what is the specific processing logic? Where does it get processed? I don’t know, and this is where reading the source code is tricky, so be sure to keep context in mind.

3. Internal functionsthrowIfCancellationRequested

Throws a Cancel if cancellation has been requested

If the action to Cancel the request has already been performed, a Cancel object is thrown

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

    if (config.signal && config.signal.aborted) {
        throw new Cancel("canceled"); }}Copy the code
  • The first judgmentcancelTokenWhether it is instantiated, and if it is instantiatedthrowIfRequestedBy means ofPrevious articleWe know thatcancelTokenIs a publisk-subscribe function that executes internal subscriber events as soon as it is instantiatedcancel, will pass if it is the first time to cancelresolvePromiseReturns aCancelThe instance
  • The second judgment is support for the FETCH API, which is not documented yet, but can be seen in an example at Axios-readme-line740

4. Distribute functionsdispatchRequest

Dispatch a request to the server using the configured adapter

Send requests to the server using 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) {
            deleteconfig.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); }); };Copy the code
  • Call throwIfCancellationRequested, if the user will take the initiative to request directly resolve or reject, no longer perform subsequent logic

  • Calls to transformData transform the date format in the request header, and.call passes the current context config

  • Call the merge function in utils to flatly process the headers object.

  • Calling the forEach function in Utils triggers the cleanHeaderConfig method each time a given array element is traversed, which removes any excess headers configurations that have been merged

  • Defines the global adapter that accepts the current instance

  • Return the adapter to perform as a result, the adapter to send an asynchronous request, need to be in the chain calls. Then (in) getting the return value, and in the process need to resolved or reject values do some processing, The processing logic is in onAdapterResolution and onAdapterRejection respectively

  • Call in onAdapterResolution and onAdapterRejection throwIfCancellationRequested, used to detect whether the user action triggers the cancellation request at this time. So there’s a problem. – What’s the point of doing this when the request has already been sent and the result has even been returned? A, performance can be improved in order not to execute subsequent logic.

Tips: For flattening arrays, please refer to Ruan Yifeng’s introduction to -ES6

Tips: Don’t get too entangled in the concept of adapters, future articles will delve into adapters for [Browser, Node]

Third, summary

Request distribution module of logic is relatively simple, relatively complicated place may be on the throwIfCancellationRequested calls and continues the context. ThrowIfCancellationRequested personal understanding is one of users active request of export, the export of the execution time is request has been sent yet response or have a response. In contrast to the previous Cancel module, where the exit is in the executor, ajax requests from the client and repeated requests from Node before or after the HTTP request is established will be executed earlier or later than the exit in the current DispatchRequest.

Four, reference

1. Xianling Pavilion article detailed interpretation of Axios source code

2. Lin Jingyi article Lin Jingyi Notepad – Axios source analysis (five) : the core tool method

3. Wakakawa’s article studied the overall architecture of AXIos source code to build his own request library

4. Jie Ling’s article reads axios source code in depth