Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js 环境。在浏览器端,Axios 的底层实现是基于原生的 XMLHttpRequest
(XHR)。它对 XHR 进行了封装,增加了 Promise 支持、自动转换 JSON 数据、请求和响应拦截器等功能。在 Node.js 环境中,Axios 使用 http
模块来发起请求。
定义:XHR 是一个较旧的 API,用于在浏览器中发起网络请求。
工作原理:基于事件驱动,通过监听 onreadystatechange
事件来处理请求状态变化。
优点:
兼容性好,支持较旧的浏览器。
提供了丰富的 API,可以实现复杂的网络请求操作。
缺点:
基于回调,容易导致回调地狱,代码难以维护。
无法中止请求。
需要手动设置请求头和解析响应。
使用场景:适用于需要兼容旧浏览器的场景。
定义:Fetch 是一个现代的、基于 Promise 的网络请求接口,用于替代 XHR。
工作原理:基于 Promise,使用 Promise
对象来处理异步请求。
优点:
语法简洁,使用 Promise 避免了回调地狱。
支持中止请求(通过 AbortController
)。
更好的错误处理。
支持流式传输,适用于大文件上传和下载。
缺点:
兼容性较差,在一些较老的浏览器中不支持。
响应处理需要手动调用 .json()
或 .text()
等方法。
默认不接受跨域请求,需要通过 CORS 配置。
使用场景:适用于现代 Web 开发,不需要考虑较旧浏览器版本的场景。
定义:Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js 环境。
工作原理:本质上是对 XHR 的封装,在浏览器端使用 XHR,在 Node.js 中使用 http
模块。
优点:
基于 Promise,支持 async/await
。
自动转换 JSON 数据。
支持请求和响应拦截器。
能够取消请求。
缺点:
需要额外引入库。
在一些极端情况下(如超时控制)可能不如原生 Fetch 灵活。
使用场景:适用于需要更丰富的功能(如拦截器、自动数据转换)的场景。
Axios 的请求返回的是一个 Promise 对象,这使得它能够很方便地进行异步操作的处理。例如,你可以使用 .then()
方法来处理请求成功的情况,使用 .catch()
方法来处理请求失败的情况。比如:
axios.get('/user')
.then(response => {
console.log(response.data); // 处理成功响应
})
.catch(error => {
console.error(error); // 处理错误
});
Axios GET 和 POST 示例
获取的数据:
{{ data }}
POST 请求的响应:
{{ postDataResponse }}
GET
请求使用 axios.get
方法发起 GET
请求。
请求的 URL 是 https://jsonplaceholder.typicode.com/posts/1
,这是一个公共的测试 API,返回一个模拟的帖子数据。
请求成功后,将响应数据存储到 data
属性中,并在页面上显示。
POST
请求使用 axios.post
方法发起 POST
请求。
请求的 URL 是 https://jsonplaceholder.typicode.com/posts
,同样是一个公共的测试 API。
请求体是一个包含 title
、body
和 userId
的对象。
请求成功后,将响应数据存储到 postDataResponse
属性中,并在页面上显示。
async/await
methods: {
async fetchData() {
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/posts/1');
this.data = response.data;
} catch (error) {
console.error('GET 请求失败:', error);
}
},
async postData() {
const postData = {
title: 'foo',
body: 'bar',
userId: 1,
};
try {
const response = await axios.post('https://jsonplaceholder.typicode.com/posts', postData);
this.postDataResponse = response.data;
} catch (error) {
console.error('POST 请求失败:', error);
}
},
},
Axios 请求头和查询参数示例
响应数据:
{{ response }}
在 axios.get
方法中,通过 headers
属性传递自定义请求头。
示例中添加了 Authorization
和 Custom-Header
两个请求头。
在 axios.get
方法中,通过 params
属性传递查询参数。
查询参数会自动被 Axios 转换为 URL 的查询字符串。例如,params
对象 { userId: 1, limit: 10 }
会被转换为 ?userId=1&limit=10
。
假设请求头和查询参数都设置好后,最终的请求 URL 会类似于:
https://jsonplaceholder.typicode.com/posts?userId=1&limit=10&status=active
async/await
methods: {
async fetchWithHeadersAndParams() {
const headers = {
'Authorization': 'Bearer your_token_here',
'Custom-Header': 'CustomValue',
};
const params = {
userId: 1,
limit: 10,
status: 'active',
};
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/posts', {
headers: headers,
params: params,
});
this.response = response.data;
} catch (error) {
console.error('请求失败:', error);
this.response = { error: error.message };
}
},
},
在 Vue 项目中使用 Axios 发送请求时,可以通过配置请求体的格式来满足不同的需求。以下是三种常见的请求体格式的示例:application/x-www-form-urlencoded
、multipart/form-data
和 application/json
。
Axios 请求体格式示例
响应数据:
{{ response }}
使用 URLSearchParams
构造请求体。
Axios 会自动将 URLSearchParams
转换为 application/x-www-form-urlencoded
格式。
示例代码:
const data = new URLSearchParams();
data.append('username', 'kimi');
data.append('password', '123456');
axios.post('https://jsonplaceholder.typicode.com/posts', data);
使用 FormData
构造请求体。
需要手动设置请求头 Content-Type
为 multipart/form-data
。
示例代码:
const formData = new FormData();
formData.append('file', new Blob(['Hello World'], { type: 'text/plain' }), 'example.txt');
formData.append('description', 'This is a test file');
axios.post('https://jsonplaceholder.typicode.com/posts', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
直接发送一个 JavaScript 对象。
Axios 会自动将对象序列化为 JSON 格式,并设置请求头 Content-Type
为 application/json
。
示例代码:
const data = {
title: 'foo',
body: 'bar',
userId: 1,
};
axios.post('https://jsonplaceholder.typicode.com/posts', data);
以下是一些常用的 Axios 默认配置项:
配置项 | 描述 |
---|---|
baseURL |
基础 URL,请求时会自动拼接 |
headers |
请求头,可以设置通用头或特定方法的头 |
timeout |
请求超时时间(单位为毫秒) |
withCredentials |
是否允许跨域请求携带凭证(如 cookies) |
responseType |
响应数据类型(如 json 、text 、arraybuffer 等) |
validateStatus |
定义哪些状态码被视为成功响应 |
transformRequest |
请求发送前的数据转换函数 |
transformResponse |
响应数据的转换函数 |
以下是一个完整的示例,展示如何设置全局默认配置和自定义实例默认配置:
// 设置全局默认配置
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = 'Bearer your_token_here';
axios.defaults.timeout = 3000;
// 创建自定义实例
const customInstance = axios.create({
baseURL: 'https://api.custom.com',
headers: {
'Content-Type': 'application/json'
}
});
// 修改实例的默认配置
customInstance.defaults.timeout = 5000;
// 使用全局配置发起请求
axios.get('/user').then(response => {
console.log(response.data);
});
// 使用自定义实例发起请求
customInstance.get('/custom-user').then(response => {
console.log(response.data);
});
Axios 允许通过 axios.defaults
设置全局默认配置,这些配置将应用于所有通过 axios
发起的请求。以下是一些常见的全局默认配置:
基础 URL (baseURL
):为所有请求设置一个基础 URL,请求的 URL 会自动拼接在 baseURL
后面。
axios.defaults.baseURL = 'https://api.example.com';
请求头 (headers
):设置通用的请求头或特定方法的请求头。
axios.defaults.headers.common['Authorization'] = 'Bearer your_token_here';
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
超时时间 (timeout
):设置请求的超时时间(单位为毫秒),超过该时间未响应则请求会被中断。
axios.defaults.timeout = 2500; // 2.5 秒
验证状态码 (validateStatus
):定义哪些 HTTP 状态码被视为成功响应。
axios.defaults.validateStatus = function (status) {
return status >= 200 && status < 300; // 默认值
};
除了全局配置,Axios 还允许创建自定义实例,并为每个实例设置默认配置。这在项目中需要使用多个不同配置的 Axios 实例时非常有用:
const instance = axios.create({
baseURL: 'https://api.example.com',
timeout: 3000,
headers: {
'Authorization': 'Bearer your_token_here'
}
});
// 修改实例的默认配置
instance.defaults.headers.common['Custom-Header'] = 'CustomValue';
Axios 的配置会按优先级合并,优先级从低到高依次为:
库默认值:在 lib/defaults.js
中定义的默认值。
实例的 defaults
属性:通过 axios.create()
创建的实例的默认配置。
请求的 config
参数:在每次请求中传递的配置参数。
const instance = axios.create({
timeout: 2500 // 实例默认超时时间
});
instance.get('/longRequest', {
timeout: 5000 // 该请求的超时时间覆盖实例默认值
});
在使用 Axios 发起 HTTP 请求时,响应数据的格式和状态码是两个非常重要的部分。Axios 提供了丰富的响应数据结构,同时允许你根据状态码来处理不同的响应情况。
当 Axios 发起请求并收到响应时,它会返回一个响应对象,该对象包含以下属性:
data
:响应体的内容。Axios 会根据 Content-Type
自动解析响应体。如果是 application/json
,它会被解析为 JavaScript 对象。
status
:HTTP 状态码(如 200
、404
、500
等)。
statusText
:HTTP 状态消息(如 OK
、Not Found
、Internal Server Error
等)。
headers
:响应头,是一个对象,包含服务器返回的所有响应头。
config
:请求的配置对象,包含了请求时传递的配置信息。
request
:原生的请求对象(在浏览器中是 XMLHttpRequest
,在 Node.js 中是 http.ClientRequest
)。
以下是一个示例,展示如何处理 Axios 的响应数据:
import axios from 'axios';
axios.get('https://jsonplaceholder.typicode.com/posts/1')
.then(response => {
console.log('响应数据:', response.data); // 响应体内容
console.log('状态码:', response.status); // HTTP 状态码
console.log('状态消息:', response.statusText); // HTTP 状态消息
console.log('响应头:', response.headers); // 响应头
console.log('请求配置:', response.config); // 请求配置
})
.catch(error => {
console.error('请求失败:', error);
});
HTTP 状态码是服务器对请求的响应状态的描述。常见的状态码包括:
2xx:成功
200 OK
:请求成功。
201 Created
:请求成功,且服务器创建了新资源。
204 No Content
:请求成功,但没有返回内容。
3xx:重定向
301 Moved Permanently
:请求的资源已永久移动到新位置。
302 Found
:请求的资源临时移动到新位置。
4xx:客户端错误
400 Bad Request
:请求格式错误。
401 Unauthorized
:未授权,需要认证。
403 Forbidden
:禁止访问。
404 Not Found
:请求的资源不存在。
5xx:服务器错误
500 Internal Server Error
:服务器内部错误。
502 Bad Gateway
:网关错误。
503 Service Unavailable
:服务不可用。
以下是一个示例,展示如何根据状态码处理不同的响应情况:
import axios from 'axios';
axios.get('https://jsonplaceholder.typicode.com/posts/1')
.then(response => {
console.log('响应数据:', response.data);
// 根据状态码处理响应
switch (response.status) {
case 200:
console.log('请求成功:', response.data);
break;
case 404:
console.error('资源未找到');
break;
case 500:
console.error('服务器内部错误');
break;
default:
console.log('其他状态码:', response.status);
}
})
.catch(error => {
console.error('请求失败:', error);
// 处理错误响应
if (error.response) {
console.error('状态码:', error.response.status);
console.error('状态消息:', error.response.statusText);
} else if (error.request) {
console.error('请求已发送,但未收到响应');
} else {
console.error('请求配置错误:', error.message);
}
});
你可以通过 validateStatus
配置项自定义哪些状态码被视为成功响应。默认情况下,只有 2xx
状态码被视为成功,但你可以修改这个行为:
import axios from 'axios';
axios.get('https://jsonplaceholder.typicode.com/posts/1', {
validateStatus: function (status) {
return status >= 200 && status < 400; // 将 2xx 和 3xx 状态码视为成功
}
})
.then(response => {
console.log('响应数据:', response.data);
})
.catch(error => {
console.error('请求失败:', error);
});
Axios 的请求拦截器和响应拦截器是 Axios 提供的强大功能,用于在请求发送之前和响应返回之后对数据进行处理。它们可以用于多种场景,例如统一设置请求头、添加认证信息、处理错误、格式化响应数据等。
请求拦截器可以在请求发送之前对请求进行处理。你可以通过 axios.interceptors.request.use()
方法添加请求拦截器。
以下是一个示例,展示如何在请求拦截器中统一设置请求头和添加认证信息:
import axios from 'axios';
// 添加请求拦截器
axios.interceptors.request.use(
config => {
// 在发送请求之前做些什么
config.headers['Authorization'] = 'Bearer your_token_here'; // 添加认证信息
config.headers['Custom-Header'] = 'CustomValue'; // 添加自定义请求头
return config;
},
error => {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 测试请求
axios.get('https://jsonplaceholder.typicode.com/posts/1')
.then(response => {
console.log('响应数据:', response.data);
})
.catch(error => {
console.error('请求失败:', error);
});
响应拦截器可以在响应返回之后对响应进行处理。你可以通过 axios.interceptors.response.use()
方法添加响应拦截器。
以下是一个示例,展示如何在响应拦截器中统一处理响应数据和错误:
import axios from 'axios';
// 添加响应拦截器
axios.interceptors.response.use(
response => {
// 对响应数据做点什么
console.log('响应状态码:', response.status);
return response.data; // 只返回响应数据
},
error => {
// 对响应错误做点什么
if (error.response) {
// 请求已发出,但服务器响应的状态码不在 2xx 范围内
console.error('响应状态码:', error.response.status);
console.error('响应消息:', error.response.statusText);
} else if (error.request) {
// 请求已发出,但没有收到响应
console.error('请求已发出,但未收到响应');
} else {
// 在设置请求时发生了一些事情,触发了一个错误
console.error('请求配置错误:', error.message);
}
return Promise.reject(error);
}
);
// 测试请求
axios.get('https://jsonplaceholder.typicode.com/posts/1')
.then(response => {
console.log('响应数据:', response);
})
.catch(error => {
console.error('请求失败:', error);
});
除了全局拦截器,你还可以为自定义的 Axios 实例添加拦截器。这在项目中需要使用多个不同配置的 Axios 实例时非常有用。
import axios from 'axios';
// 创建自定义实例
const customInstance = axios.create({
baseURL: 'https://api.example.com',
timeout: 3000,
});
// 为自定义实例添加请求拦截器
customInstance.interceptors.request.use(
config => {
config.headers['Authorization'] = 'Bearer your_token_here';
return config;
},
error => {
return Promise.reject(error);
}
);
// 为自定义实例添加响应拦截器
customInstance.interceptors.response.use(
response => {
return response.data; // 只返回响应数据
},
error => {
console.error('请求失败:', error);
return Promise.reject(error);
}
);
// 使用自定义实例发起请求
customInstance.get('/posts/1')
.then(response => {
console.log('响应数据:', response);
})
.catch(error => {
console.error('请求失败:', error);
});
如果需要移除某个拦截器,可以通过返回的 id
来移除它:
import axios from 'axios';
// 添加请求拦截器并获取 id
const requestInterceptorId = axios.interceptors.request.use(
config => {
config.headers['Authorization'] = 'Bearer your_token_here';
return config;
},
error => {
return Promise.reject(error);
}
);
// 移除请求拦截器
axios.interceptors.request.eject(requestInterceptorId);
// 添加响应拦截器并获取 id
const responseInterceptorId = axios.interceptors.response.use(
response => {
return response.data;
},
error => {
return Promise.reject(error);
}
);
// 移除响应拦截器
axios.interceptors.response.eject(responseInterceptorId);
统一设置请求头:例如,添加认证信息(如 Authorization
)、内容类型(如 Content-Type
)等。
添加公共参数:例如,为每个请求添加时间戳或用户 ID。
请求取消:通过 CancelToken
或 AbortController
实现请求取消功能。
统一处理响应数据:例如,只返回响应体中的数据部分。
统一处理错误:例如,根据状态码显示不同的错误消息。
处理重定向:例如,根据状态码(如 401
)跳转到登录页面。