Axios核心原理

Axios 是一个基于 Promise 的 HTTP 客户端,它可以用于浏览器和 Node.js。其核心原理主要包括以下几个部分:

  1. 请求流程

Axios 的请求流程主要包括以下步骤:

创建实例:axios.create() 方法可以创建一个具有默认配置的 Axios 实例。

请求拦截器:在请求发送前,可以使用 axios.interceptors.request.use() 进行修改,如添加 token、修改 headers。

请求适配器:在浏览器环境中,Axios 通过 XMLHttpRequest(XHR) 发送请求,在 Node.js 环境中使用 http 模块。

响应拦截器:在请求返回后,axios.interceptors.response.use() 允许对响应数据进行处理,比如格式化数据或错误处理。


  1. 核心模块

Axios 主要由以下几个核心模块组成:

(1) Axios 类

Axios 是核心类,所有的请求都通过 Axios.prototype.request(config) 进行处理:

class Axios {

constructor(defaultConfig) {

this.defaults = defaultConfig;

this.interceptors = {

request: new InterceptorManager(),

response: new InterceptorManager(),

};

}

request(config) {

// 处理请求配置

config = mergeConfig(this.defaults, config);

复制代码
// 构造拦截器链
let chain = [
  { fulfilled: dispatchRequest, rejected: undefined }
];

// 先添加请求拦截器
this.interceptors.request.forEach(interceptor => {
  chain.unshift(interceptor);
});

// 再添加响应拦截器
this.interceptors.response.forEach(interceptor => {
  chain.push(interceptor);
});

// 执行拦截器链
let promise = Promise.resolve(config);
while (chain.length) {
  const { fulfilled, rejected } = chain.shift();
  promise = promise.then(fulfilled, rejected);
}

return promise;

}

}


(2) 拦截器 (InterceptorManager)

Axios 内部使用 InterceptorManager 管理拦截器,它的结构如下:

class InterceptorManager {

constructor() {

this.handlers = [];

}

use(fulfilled, rejected) {

this.handlers.push({ fulfilled, rejected });

}

forEach(fn) {

this.handlers.forEach(fn);

}

}

拦截器的执行顺序:

请求拦截器:先进后出(后添加的先执行)

响应拦截器:先进先出(先添加的先执行)


(3) 适配器 (adapters)

Axios 需要兼容不同的运行环境,因此通过适配器模式进行封装:

在 浏览器 环境下,使用 XMLHttpRequest 发送请求:

function xhrAdapter(config) {

return new Promise((resolve, reject) => {

const request = new XMLHttpRequest();

request.open(config.method.toUpperCase(), config.url, true);

复制代码
request.onload = function () {
  resolve({
    data: request.responseText,
    status: request.status,
    headers: parseHeaders(request.getAllResponseHeaders()),
    config,
  });
};

request.onerror = function () {
  reject(new Error("Network Error"));
};

request.send(config.data);

});

}

在 Node.js 环境下,使用 http 模块:

function httpAdapter(config) {

return new Promise((resolve, reject) => {

const http = require('http');

const req = http.request(config.url, (res) => {

let data = '';

res.on('data', chunk => data += chunk);

res.on('end', () => resolve({ data, status: res.statusCode }));

});

复制代码
req.on('error', reject);
req.write(config.data || '');
req.end();

});

}


(4) dispatchRequest 发送请求

dispatchRequest 负责选择适配器并发送请求:

function dispatchRequest(config) {

const adapter = config.adapter || (typeof XMLHttpRequest !== 'undefined' ? xhrAdapter : httpAdapter);

return adapter(config).then(response => {

return response;

});

}


  1. Axios 其他功能

(1) axios.create()

可以创建一个自定义实例,带有默认 config:

const instance = axios.create({

baseURL: 'https://api.example.com',

timeout: 1000,

});

instance.get('/user');

(2) 取消请求 (CancelToken)

Axios 允许取消请求,核心原理是 AbortController:

const controller = new AbortController();

axios.get('/user', { signal: controller.signal }).catch(err => console.log(err));

// 取消请求

controller.abort();

(3) 并发请求 (axios.all())

可以使用 Promise.all 进行并发请求:

axios.all([axios.get('/user'), axios.get('/posts')])

.then(axios.spread((user, posts) => {

console.log(user.data, posts.data);

}));


  1. 总结

核心架构

  1. Axios 类:处理请求逻辑

  2. InterceptorManager:管理请求/响应拦截器

  3. dispatchRequest:调用适配器发送请求

  4. xhrAdapter & httpAdapter:兼容不同环境

拦截器机制

先进后出执行请求拦截器

先进先出执行响应拦截器

功能

axios.create():创建实例

axios.CancelToken:取消请求

axios.all():并发请求

这样,Axios 通过模块化设计,提供了一种可扩展、兼容性强的 HTTP 请求解决方案。


Axios 之所以被称为"基于 Promise 的 HTTP 客户端",是因为它的内部实现依赖于 Promise 机制 来处理异步请求,并提供了链式调用的能力。


  1. 传统回调与 Promise 的区别

在使用 XMLHttpRequest 进行网络请求时,通常需要通过 回调函数 处理异步请求:

const xhr = new XMLHttpRequest();

xhr.open('GET', 'https://api.example.com/data', true);

xhr.onreadystatechange = function () {

if (xhr.readyState === 4 && xhr.status === 200) {

console.log(JSON.parse(xhr.responseText));

}

};

xhr.send();

这种写法可读性较差,且多个异步操作嵌套时会形成 回调地狱。

而 Promise 允许我们以更清晰的方式处理异步操作:

fetch('https://api.example.com/data')

.then(response => response.json())

.then(data => console.log(data))

.catch(error => console.error(error));

Axios 也是采用 Promise 方式 来封装 XMLHttpRequest,避免了回调地狱,并提供更强的扩展性。


  1. Axios 如何使用 Promise

Axios 的核心方法 axios(config) 或 axios.get(url) 返回的其实是一个 Promise:

axios.get('https://api.example.com/data')

.then(response => {

console.log(response.data); // 请求成功时处理数据

})

.catch(error => {

console.error(error); // 请求失败时捕获错误

});

从外部使用上,Axios 提供了标准的 Promise 语法,可以使用 .then() 处理成功结果,使用 .catch() 处理错误,还可以使用 .finally() 进行清理工作。


  1. Axios 内部基于 Promise 处理请求

Axios 在内部通过 Promise.resolve(config) 让请求流程变成一个 Promise 链:

Axios.prototype.request = function (config) {

let promise = Promise.resolve(config);

// 处理拦截器

const chain = [dispatchRequest, undefined]; // 发送请求的函数

this.interceptors.request.forEach(interceptor => {

chain.unshift(interceptor.fulfilled, interceptor.rejected);

});

this.interceptors.response.forEach(interceptor => {

chain.push(interceptor.fulfilled, interceptor.rejected);

});

while (chain.length) {

promise = promise.then(chain.shift(), chain.shift());

}

return promise;

};

Promise.resolve(config) 确保整个流程是异步执行的。

chain 维护一个拦截器队列,使得 请求拦截器 -> 发送请求 -> 响应拦截器 形成一个 Promise 链。

最终,返回的 Promise 允许调用 .then()、.catch() 处理异步逻辑。


  1. 支持 Promise 并发操作

Axios 还支持 axios.all() 进行多个异步请求的并发处理:

axios.all([

axios.get('/user'),

axios.get('/orders')

])

.then(axios.spread((user, orders) => {

console.log(user.data, orders.data);

}))

.catch(error => console.error(error));

axios.all() 的本质是基于 Promise.all(),它会并行执行多个请求,并在所有请求完成后返回结果。


  1. 总结

  2. Axios 采用 Promise 进行封装,避免了 XMLHttpRequest 的回调嵌套问题,使代码更加简洁。

  3. 内部基于 Promise 处理请求拦截器、发送请求、响应拦截器,形成完整的 Promise 链。

  4. 返回标准 Promise 对象,支持 .then() 处理成功结果,.catch() 处理错误,.finally() 进行清理。

  5. 支持 Promise 并发操作,比如 axios.all(),提升异步操作的能力。

因此,Axios 是 基于 Promise 设计的 HTTP 客户端,它利用 Promise 提供的链式调用、错误处理、并发能力,让网络请求管理更加优雅。


Axios 被称为 HTTP 客户端,主要是因为它封装了 HTTP 请求 的发送、处理和管理,提供了类似于浏览器 fetch 或 XMLHttpRequest 的功能,但比原生 API 更强大和易用。以下是 Axios 作为 HTTP 客户端 的关键特性:


  1. Axios 是一个 HTTP 客户端

Axios 主要用于 向服务器发送 HTTP 请求 并 处理 HTTP 响应,它支持:

GET(获取资源)

POST(提交数据)

PUT(更新数据)

DELETE(删除数据)

PATCH(部分更新)

以及 HEAD、OPTIONS 等请求方法

示例:

axios.get('https://api.example.com/users')

.then(response => console.log(response.data))

.catch(error => console.error(error));

这个请求会发送 GET 请求到 https://api.example.com/users,然后 Axios 作为 HTTP 客户端 处理返回的响应。


  1. Axios 依赖 HTTP 协议

Axios 本质上是对 HTTP 协议的封装:

在 浏览器环境 下,使用 XMLHttpRequest 发送 HTTP 请求。

在 Node.js 环境 下,使用 http 或 https 模块发送 HTTP 请求。

适配器示例:

const adapter = typeof XMLHttpRequest !== 'undefined' ? xhrAdapter : httpAdapter;

Axios 自动选择合适的 HTTP 传输方式,确保在不同环境下都能发送 HTTP 请求。


  1. Axios 处理 HTTP 请求与响应

Axios 作为 HTTP 客户端,提供了请求和响应处理功能,包括:

请求拦截(修改请求,例如添加 token)

自动解析 JSON

处理 HTTP 状态码

错误处理

请求超时控制

跨域请求

示例:

axios.interceptors.request.use(config => {

config.headers.Authorization = 'Bearer token';

return config;

});

这里的拦截器为 HTTP 请求 添加身份验证头部,这正是 HTTP 客户端的常见功能之一。


  1. Axios 提供 HTTP 相关功能

Axios 作为 HTTP 客户端,提供了一些常见的 HTTP 相关功能:

  1. 自动解析响应数据

axios.get('/data').then(response => console.log(response.data));

Axios 自动将 JSON 响应解析为 JavaScript 对象,而 XMLHttpRequest 需要手动 JSON.parse(responseText)。

  1. 请求超时控制

axios.get('/slow-api', { timeout: 5000 })

.catch(error => console.log('请求超时', error));

超过 5s 后会自动取消请求。

  1. 设置请求头

axios.post('/submit', data, {

headers: { 'Content-Type': 'application/json' }

});

可以轻松设置 HTTP 头部。

  1. 取消 HTTP 请求

const controller = new AbortController();

axios.get('/data', { signal: controller.signal });

// 取消请求

controller.abort();

这在处理 防抖 和 组件卸载时清理请求 时非常有用。

  1. 支持并发请求

axios.all([

axios.get('/user'),

axios.get('/posts')

]).then(axios.spread((user, posts) => {

console.log(user.data, posts.data);

}));

Axios 允许多个 HTTP 请求 并行执行,然后合并结果。


  1. 总结

Axios 是 HTTP 客户端,因为:

  1. 它的核心功能是发送 HTTP 请求(如 GET、POST)。

  2. 它基于 HTTP 协议,支持 HTTP 头部、状态码、跨域等特性。

  3. 它封装了底层 HTTP 请求逻辑,在浏览器用 XMLHttpRequest,在 Node.js 用 http 模块。

  4. 它提供了完整的 HTTP 请求生命周期管理(拦截、超时、错误处理等)。

  5. 它能处理多个 HTTP 请求的并发、取消、自动解析等增强功能。

因此,Axios 是一个 强大、灵活、易用的 HTTP 客户端,让开发者可以更高效地与后端 API 进行交互。

相关推荐
灵感__idea1 小时前
JavaScript高级程序设计(第5版):扎实的基本功是唯一捷径
前端·javascript·程序员
摇滚侠1 小时前
Vue3 其它API toRow和markRow
前端·javascript
難釋懷1 小时前
JavaScript基础-history 对象
开发语言·前端·javascript
beibeibeiooo2 小时前
【CSS3】04-标准流 + 浮动 + flex布局
前端·html·css3
拉不动的猪2 小时前
刷刷题47(react常规面试题2)
前端·javascript·面试
浪遏2 小时前
场景题:大文件上传 ?| 过总字节一面😱
前端·javascript·面试
Bigger2 小时前
Tauri(十八)——如何开发 Tauri 插件
前端·rust·app
355984268550553 小时前
医保服务平台 Webpack逆向
前端·webpack·node.js
百锦再3 小时前
React编程的核心概念:发布-订阅模型、背压与异步非阻塞
前端·javascript·react.js·前端框架·json·ecmascript·html5
thinkQuadratic3 小时前
scss预处理器对比css的优点以及基本的使用
前端·css·scss