返回

剖析迷你版axios,通晓axios的原理

前端

正文

在现代Web开发中,axios是一个不可或缺的利器,它能够轻松实现各种HTTP请求,使前后端数据交互变得轻而易举。然而,你是否真正理解axios的运作原理呢?今天,我们就将动手实现一个迷你版的axios,以此彻底掌握它的奥秘。

一、构建请求基础

首先,我们需要构建一个基础的请求函数,它将成为迷你版axios的核心。这个函数接受三个参数:

  1. URL:要请求的资源地址。
  2. data:要发送的数据,通常为一个对象。
  3. config:一个可选的配置对象,用于设置请求的选项。
function request(url, data, config) {
  // 创建XMLHttpRequest对象
  const xhr = new XMLHttpRequest();

  // 设置请求头
  xhr.setRequestHeader('Content-Type', 'application/json');

  // 监听请求状态变化
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      if (xhr.status >= 200 && xhr.status < 300) {
        // 请求成功
        console.log(xhr.responseText);
      } else {
        // 请求失败
        console.error(xhr.statusText);
      }
    }
  };

  // 打开请求
  xhr.open('GET', url);

  // 发送请求
  xhr.send(JSON.stringify(data));
}

二、实现拦截器

拦截器是axios的一个重要特性,它允许我们在请求发出前或收到响应后对请求或响应进行处理。要实现拦截器,我们需要定义一个拦截器类,它包含两个函数:

  1. request:在请求发出前执行的函数。
  2. response:在收到响应后执行的函数。
class Interceptor {
  constructor(request, response) {
    this.request = request;
    this.response = response;
  }
}

然后,我们需要在请求函数中添加对拦截器的支持。

function request(url, data, config) {
  // 创建XMLHttpRequest对象
  const xhr = new XMLHttpRequest();

  // 设置请求头
  xhr.setRequestHeader('Content-Type', 'application/json');

  // 获取拦截器
  const interceptors = config?.interceptors;

  // 如果有拦截器,则先执行请求拦截器
  if (interceptors) {
    interceptors.forEach((interceptor) => {
      interceptor.request(config);
    });
  }

  // 监听请求状态变化
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      if (xhr.status >= 200 && xhr.status < 300) {
        // 请求成功
        // 如果有拦截器,则先执行响应拦截器
        if (interceptors) {
          interceptors.forEach((interceptor) => {
            interceptor.response(xhr.responseText);
          });
        }
        console.log(xhr.responseText);
      } else {
        // 请求失败
        console.error(xhr.statusText);
      }
    }
  };

  // 打开请求
  xhr.open('GET', url);

  // 发送请求
  xhr.send(JSON.stringify(data));
}

三、完善迷你版axios

现在,我们需要将迷你版axios封装成一个对象,并添加更多功能,使其更加完善。

class Axios {
  constructor() {
    this.interceptors = [];
  }

  request(url, data, config) {
    // 创建XMLHttpRequest对象
    const xhr = new XMLHttpRequest();

    // 设置请求头
    xhr.setRequestHeader('Content-Type', 'application/json');

    // 获取拦截器
    const interceptors = config?.interceptors;

    // 如果有拦截器,则先执行请求拦截器
    if (interceptors) {
      interceptors.forEach((interceptor) => {
        interceptor.request(config);
      });
    }

    // 监听请求状态变化
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status >= 200 && xhr.status < 300) {
          // 请求成功
          // 如果有拦截器,则先执行响应拦截器
          if (interceptors) {
            interceptors.forEach((interceptor) => {
              interceptor.response(xhr.responseText);
            });
          }
          console.log(xhr.responseText);
        } else {
          // 请求失败
          console.error(xhr.statusText);
        }
      }
    };

    // 打开请求
    xhr.open('GET', url);

    // 发送请求
    xhr.send(JSON.stringify(data));
  }

  get(url, config) {
    this.request(url, null, config);
  }

  post(url, data, config) {
    this.request(url, data, config);
  }

  put(url, data, config) {
    this.request(url, data, config);
  }

  delete(url, config) {
    this.request(url, null, config);
  }

  use(interceptor) {
    this.interceptors.push(interceptor);
  }
}

至此,我们的迷你版axios就完成了!它拥有基本的请求功能,还支持拦截器,可以满足大部分的HTTP请求场景。

四、结语

通过动手实现迷你版axios,我们深入了解了axios的内部原理,包括请求流程、拦截器的运作方式等。这些知识对于掌握axios的使用和开发自定义网络请求库都非常重要。希望这篇文章能够帮助您更好地理解axios,并将其应用到您的项目中。