在前端开发中,HTTP请求是构建网络应用的基础。Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 node.js。它有很多实用功能,如请求和响应拦截、转换请求和响应数据等。通过分析 axios 的源码,我们可以深入了解前端 HTTP 请求的内部机制。

一、Axios 的基本使用

首先,我们来简单介绍一下 Axios 的基本使用方法:

// 引入 Axios
const axios = require('axios');

// 发送 GET 请求
axios.get('/user?ID=12345')
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

// 发送 POST 请求
axios.post('/user', { firstName: 'John', lastName: 'Doe' })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

二、Axios 源码结构

Axios 的源码结构相对清晰,主要由以下几个部分组成:

  1. axios:主入口文件,包含 Axios 类的定义。
  2. lib:核心功能实现,包括请求发送、响应处理、拦截器等。
  3. core:核心工具类,如取消请求、转换请求和响应数据等。
  4. helpers:辅助函数,如合并请求头、处理 URL 等。
  5. utils:工具函数,如深拷贝、扩展函数等。

三、Axios 请求流程

以下是 Axios 请求的基本流程:

  1. 创建一个 Axios 实例。
  2. 使用实例发送请求。
  3. Axios 使用 xhr 或 fetch 发送请求。
  4. 请求被发送到服务器,服务器处理请求并返回响应。
  5. Axios 接收响应,通过拦截器处理响应。
  6. 将响应结果返回给调用者。

四、Axios 源码分析

1. Axios 类

Axios 类主要包含以下方法:

  • axios#request:发送请求的核心方法。
  • axios#getaxios#post 等:封装了 request 方法,针对不同请求方式提供便捷的接口。
  • axios#interceptors:拦截器配置。
function Axios(instanceConfig) {
  this.defaults = instanceConfig;
  this.interceptors = {
    request: {},
    response: {}
  };
}

2. request 方法

request 方法是 Axios 发送请求的核心方法,主要包含以下步骤:

  1. 合并请求配置。
  2. 创建请求实例。
  3. 设置请求拦截器。
  4. 发送请求。
  5. 设置响应拦截器。
  6. 返回请求结果。
Axios.prototype.request = function (config) {
  // 合并请求配置
  config = mergeConfig(this.defaults, config);

  // 创建请求实例
  var request = new Request(config);

  // 设置请求拦截器
  var chain = [dispatchRequest, undefined];
  var promise = Promise.resolve(request);

  this.interceptors.request.forEach(function (interceptor) {
    promise = promise.then(interceptor.fulfilled, interceptor.rejected);
  });

  promise = promise.then(function (response) {
    return response;
  });

  this.interceptors.response.forEach(function (interceptor) {
    promise = promise.then(interceptor.fulfilled, interceptor.rejected);
  });

  return promise;
};

3. dispatchRequest 方法

dispatchRequest 方法负责发送请求,使用 xhr 或 fetch。以下是 xhr 的实现:

function xhrAdapter(config) {
  return new Promise(function (resolve, reject) {
    var xhr = new XMLHttpRequest();
    var url = buildURL(config.url, config.params, config.paramsSerializer);

    // 设置请求头部
    function setHeader(xhr) {
      if (config.headers) {
        Object.keys(config.headers).forEach(function (name) {
          xhr.setRequestHeader(name, config.headers[name]);
        });
      }
    }

    // 设置请求方法
    xhr.open(config.method.toUpperCase(), url, true);

    // 设置超时
    xhr.timeout = config.timeout;

    // 设置请求头部
    setHeader(xhr);

    // 处理响应
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status >= 200 && xhr.status < 300) {
          resolve(xhr.response);
        } else {
          reject(new Error('Request failed with status ' + xhr.status));
        }
      }
    };

    // 处理超时
    xhr.ontimeout = function () {
      reject(new Error('Request timeout'));
    };

    // 处理网络错误
    xhr.onerror = function () {
      reject(new Error('Network error'));
    };

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

4. 拦截器

Axios 支持请求拦截器和响应拦截器,用于在请求发送和响应处理过程中进行操作。

Axios.prototype.interceptors.request.use(function (config) {
  // 在发送请求之前做些什么
  return config;
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error);
});

Axios.prototype.interceptors.response.use(function (response) {
  // 对响应数据做点什么
  return response;
}, function (error) {
  // 对响应错误做点什么
  return Promise.reject(error);
});

五、总结

通过分析 Axios 源码,我们可以了解到前端 HTTP 请求的内部机制,包括请求发送、响应处理、拦截器等。掌握这些知识,有助于我们更好地使用 Axios,以及解决在使用过程中遇到的问题。同时,了解源码还可以激发我们对前端技术更深入的学习兴趣。