Introduction to the

Axios is a Promise-based HTTP client that supports both a browser and a Node.js environment. It is an excellent HTTP client that is widely used in a number of Web projects. Detailed introduction can be found in official documents

For most applications, ajax requests need to be handled uniformly, and interceptors are a good way to solve this problem. In Axios it provides a request interceptor and a response interceptor to handle requests and responses respectively. They do the following:

  • Request interceptor: This class of interceptors is used to uniformly perform certain operations before a request is sent, such as adding a token field to the request header.
  • Response interceptor: This type of interceptor is used to perform certain operations after receiving a response from the server. For example, if the response status code is 401, the system automatically jumps to the login page.

Next, this article uses axios source code to illustrate how interceptors are designed and implemented.

Design and Implementation

Registration of tasks

First, use the following code to register the method with the interceptor

// request interceptor
axios.interceptors.request.use(
  config= > {
    console.log('config', config);
    return config;
  },
  err= > Promise.reject(err),
);

// response interceptor
axios.interceptors.response.use(response= > {
  console.log('response', response);
  return response;
});

// axios/lib/core/InterceptorManager.js
// Add tasks to the task list using the use method in the interceptor manager class
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
  this.handlers.push({
    fulfilled: fulfilled,
    rejected: rejected
  });
  return this.handlers.length - 1;
};


Copy the code

Scheduling of tasks

// First look at the method of creating an instance in lib/axios.js(the entry file)
function createInstance(defaultConfig) {
  var context = new Axios(defaultConfig);

  // REVIEW[epic=interceptors,seq=0] bind the request method to the axios object so that the request method can be called by axios({option})
  var instance = bind(Axios.prototype.request, context);

  // Copy axios.prototype to instance
  utils.extend(instance, Axios.prototype, context);

  // Copy context to instance
  utils.extend(instance, context);

  return instance;
}
// Focus on axios.prototype.request
Axios.prototype.request = function request(config) {
	/ /... Some code has been omitted
  // Hook up interceptors middleware
  // update [epic=interceptors,seq=2] dispatchRequest
  var chain = [dispatchRequest, undefined];
  var promise = Promise.resolve(config);

  // REVIEW[epic=interceptors,seq=4] Registers the Request task at the head of the interceptor task list
  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
    chain.unshift(interceptor.fulfilled, interceptor.rejected);
  });

  // REVIEW[epic=interceptors,seq=5] Registers the Response task at the end of the interceptor task list
  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    chain.push(interceptor.fulfilled, interceptor.rejected);
  });
  // The chain array looks like this:
  // [ ...requestInterceptor, dispatchRequest,undefined, ...responseInterceptor ]
  // This ensures the sequence of interceptors

  while (chain.length) {
    // This is a big pity, rejected. // This is a big pity, rejected
    promise = promise.then(chain.shift(), chain.shift());
  }
  return promise;
};

Copy the code

It can be seen from a different location to the task list add tasks, realized the task arrangement, reached by requestInterceptor = > Request = > responseInterceptor sequentially

Task scheduling

Task scheduling is based on this line in the request function above

  var promise = Promise.resolve(config);
  while (chain.length) {
    // This is a big pity, rejected. // This is a big pity, rejected
    promise = promise.then(chain.shift(), chain.shift());
  }
Copy the code

You can see that this is done in the order of registration, and that config needs to be returned in each task.

conclusion

In the source code reading, obviously feel, because of the accumulation of a few times before, read the source code this thing began to become not so “difficult”. But there was a bit of a problem with making it clearer when writing the document. Therefore, it draws lessons from the existing documents on the Internet, using task registration => task scheduling => task scheduling, and interpreting the code from the perspective of task.