Use native js to encapsulate axios (detailed explanation)

Summary

In vue, we use axios to call the interface, and we will also perform certain encapsulation before using it, and then use it.

Here, we mainly talk about the implementation principle of axios, and how to use native js to encapsulate an axios.

Several main methods are implemented here, including post request method, create configuration method, and interceptor method.

1. post method

Before we write the method, we must first write a class by ourselves, and the content inside does not need to be written.
Then write the post method below the class:

function iaxios () {
    
    

}

iaxios.prototype.post = function (url, data){
    
    

}

OK, now let's implement this method.

If we want to use native js to implement post requests, we should do this:

    var xhr = new XMLHttpRequest();
    xhr.open('post', url, true);
    xhr.onreadystatechange = function () {
    
    
      if (xhr.readyState == 4) {
    
    
        if ((xhr.status == 200 || xhr.status == 304)) {
    
    
          resolve(xhr.responseText)
        } else {
    
    
          reject(xhr.responseText)
        }
      }
    };
    xhr.send(data)

But if we put this code directly, there will be a little problem:

1. The official axios returns a promise object

2. The data parameter passed by the official axios.post method is an object, and the original one is a string

So in order to solve the first problem, we can return a promise object in the method, and the second problem can be solved using JSON.stringfy() method.

iaxios.prototype.post = function (url, data) {
    
    
  //返回promise对象
  return new Promise((resolve, reject) => {
    
    
    var xhr = new XMLHttpRequest();
    xhr.open('post', url, true);
    xhr.onreadystatechange = function () {
    
    
      if (xhr.readyState == 4) {
    
    
        if ((xhr.status == 200 || xhr.status == 304)) {
    
    
          resolve(xhr.responseText)
        } else {
    
    
          reject(xhr.responseText)
        }
      }
    };
    xhr.send(JSON.stringify(data))
  })
}

In this way, we have implemented the method of post.
As for the get method, I won’t write it again here (just pay attention to the parameters when writing).

2. create method

First of all, we know that the create method of axios is mainly to configure the first parameters of the request, and this method will also return an instance of axios, which can continue to use methods such as post.

So our first thought is that this method should return an instance object, and the properties under this instance object will be set according to the object passed in.

Here I only list two attributes:

iaxios.prototype.create = function (obj) {
    
    
  var emaxios = new iaxios()
  emaxios.headers = obj.headers;
  emaxios.baseUrl = obj.baseUrl;
  return emaxios;
}

But after we call the create method, we already have some configurations. If we call post and other methods again, we should call the psot method with these parameters, so we also need to modify it in the post method.

We first write a method to configure the request header:

function setHeader (xhr, headers) {
    
    
  for (var i in headers) {
    
    
    xhr.setRequestHeader(i, headers[i]);
  }
}

Then in the post method, just call this method before the ajax request is sent:

    setHeader(xhr, this.headers);

3. Interceptor

In axios, there are two types of interceptors, namely request interception and response interception.

The functions of the two are similar, one is what you want to do before the request, and the other is what you want to do after the request.

Let's first write about request interception (use is not considered here):

Let's think about it first, interceptors must be an object, and there are two attributes below, namely request and response.

Then we write in the class:

function iaxios () {
    
    
  this.interceptors = {
    
    
    request (cb) {
    
    
    
    },
    response (aa) {
    
    

    },
  }
}

If we want to call this method outside, a callback function will be passed in,
so here we need to save this callback function (considering that there are multiple interceptors, we use an array to save).

At the same time, we also need to write a data to store the data of the request (because in the callback function of the request interceptor, there is a config parameter, which contains the requested data)

function iaxios () {
    
    
  //保存拦截器中的回调函数
  this.saveRequest = []
  this.saveResponse = []
  //保存请求的数据
  this.data = {
    
    };
  let _this = this;
  this.interceptors = {
    
    
    request (cb) {
    
    
      _this.saveRequest.push(cb)
    },
    response (aa) {
    
    
      _this.saveResponse.push(aa)
    },
  }
}

Now that the interceptor method has been written, when should we call it?

Request interception must be called before the request is sent. Let's take post as an example:

iaxios.prototype.post = function (url, data) {
    
    
  this.data = data;
  let _this = this;
  // this.saveRequest && this.saveRequest(this)
  //请求之前调用请求拦截的回调函数
  if (this.saveRequest) {
    
    
    this.saveRequest.forEach(fn => {
    
    
      fn(this)
    })
  }

We only need to copy the data we want to pass (used as parameters) before the request.
Then call the method we saved in a loop (in fact, it is to pass the callback function when calling)

This will enable request interception.

Then the response interception must be called before returning the response data:

        if ((xhr.status == 200 || xhr.status == 304)) {
    
    
          //用来保存返回的数据
          let newRespose = new Object;
          newRespose.data = JSON.parse(xhr.responseText);
          //在返回数据之前调用相应拦截器的回调函数
          if (_this.saveResponse) {
    
    
            _this.saveResponse.forEach(fn => {
    
    
              fn(newRespose)
            })
          }
          resolve(newRespose.data)

The newRespose we created here is also passed as a parameter to the response interception method.

In this way, the implementation of the response interceptor is also completed.

4. Code

Finally, copy the whole code again:

// const { resolve, reject } = require("core-js/fn/promise")

function iaxios () {
    
    
  //保存拦截器中的回调函数
  this.saveRequest = []
  this.saveResponse = []
  //保存请求的数据
  this.data = {
    
    };
  let _this = this;
  this.interceptors = {
    
    
    request (cb) {
    
    
      _this.saveRequest.push(cb)
    },
    response (aa) {
    
    
      _this.saveResponse.push(aa)
    },
  }
}



iaxios.prototype.post = function (url, data) {
    
    
  this.data = data;
  let _this = this;
  // this.saveRequest && this.saveRequest(this)
  //请求之前调用请求拦截的回调函数
  if (this.saveRequest) {
    
    
    this.saveRequest.forEach(fn => {
    
    
      fn(this)
    })
  }

  //返回promise对象
  return new Promise((resolve, reject) => {
    
    
    var xhr = new XMLHttpRequest();
    xhr.open('post', url, true);
    //设置请求头的配置
    setHeader(xhr, this.headers);
    xhr.onreadystatechange = function () {
    
    
      if (xhr.readyState == 4) {
    
    
        if ((xhr.status == 200 || xhr.status == 304)) {
    
    
          //用来保存返回的数据
          let newRespose = new Object;
          newRespose.data = JSON.parse(xhr.responseText);
          // _this.saveResponse && _this.saveResponse(newRespose)
          //在返回数据之前调用相应拦截器的回调函数
          if (_this.saveResponse) {
    
    
            _this.saveResponse.forEach(fn => {
    
    
              fn(newRespose)
            })
          }
          resolve(newRespose.data)
        } else {
    
    
          reject(xhr.responseText)
        }
      }
    };
    xhr.send(JSON.stringify(data))
  })
}

iaxios.prototype.get = function (url) {
    
    
  let _this = this;
  // this.saveRequest && this.saveRequest(this)
  //请求之前调用请求拦截的回调函数
  if (this.saveRequest) {
    
    
    this.saveRequest.forEach(fn => {
    
    
      fn(this)
    })
  }

  //返回promise对象
  return new Promise((resolve, reject) => {
    
    
    var xhr = new XMLHttpRequest();
    xhr.open('get', url, true);
    //设置请求头的配置
    setHeader(xhr, this.headers);
    xhr.onreadystatechange = function () {
    
    
      if (xhr.readyState == 4) {
    
    
        if ((xhr.status == 200 || xhr.status == 304)) {
    
    
          //用来保存返回的数据
          let newRespose = new Object;
          newRespose.data = JSON.parse(xhr.responseText);
          // _this.saveResponse && _this.saveResponse(newRespose)
          //在返回数据之前调用相应拦截器的回调函数
          if (_this.saveResponse) {
    
    
            _this.saveResponse.forEach(fn => {
    
    
              fn(newRespose)
            })
          }
          resolve(newRespose.data)
        } else {
    
    
          reject(xhr.responseText)
        }
      }
    };
    xhr.send()
  })
}

//返回一个新的实例并且复制obj的属性
iaxios.prototype.create = function (obj) {
    
    
  var emaxios = new iaxios()
  emaxios.headers = obj.headers;
  emaxios.baseUrl = obj.baseUrl;
  return emaxios;
}

//设置请求头的方法
function setHeader (xhr, headers) {
    
    
  for (var i in headers) {
    
    
    xhr.setRequestHeader(i, headers[i]);
  }
}








var taxios = new iaxios();


export {
    
    
  taxios
}

Guess you like

Origin blog.csdn.net/weixin_46726346/article/details/118970057
Recommended