一、axios簡介
????????Axios 是一個基于 Promise 的 HTTP 客戶端,用于瀏覽器和 Node.js 環境。在瀏覽器端,Axios 的底層實現是基于原生的 XMLHttpRequest
(XHR)。它對 XHR 進行了封裝,增加了 Promise 支持、自動轉換 JSON 數據、請求和響應攔截器等功能。在 Node.js 環境中,Axios 使用 http
模塊來發起請求。
1.1XHR、Fetch API 和 Axios 的區別
1.?XMLHttpRequest (XHR)
-
定義:XHR 是一個較舊的 API,用于在瀏覽器中發起網絡請求。
-
工作原理:基于事件驅動,通過監聽
onreadystatechange
事件來處理請求狀態變化。 -
優點:
-
兼容性好,支持較舊的瀏覽器。
-
提供了豐富的 API,可以實現復雜的網絡請求操作。
-
-
缺點:
-
基于回調,容易導致回調地獄,代碼難以維護。
-
無法中止請求。
-
需要手動設置請求頭和解析響應。
-
-
使用場景:適用于需要兼容舊瀏覽器的場景。
?Fetch API
-
定義:Fetch 是一個現代的、基于 Promise 的網絡請求接口,用于替代 XHR。
-
工作原理:基于 Promise,使用
Promise
對象來處理異步請求。 -
優點:
-
語法簡潔,使用 Promise 避免了回調地獄。
-
支持中止請求(通過
AbortController
)。 -
更好的錯誤處理。
-
支持流式傳輸,適用于大文件上傳和下載。
-
-
缺點:
-
兼容性較差,在一些較老的瀏覽器中不支持。
-
響應處理需要手動調用
.json()
或.text()
等方法。 -
默認不接受跨域請求,需要通過 CORS 配置。
-
-
使用場景:適用于現代 Web 開發,不需要考慮較舊瀏覽器版本的場景。
3.?Axios
-
定義:Axios 是一個基于 Promise 的 HTTP 客戶端,用于瀏覽器和 Node.js 環境。
-
工作原理:本質上是對 XHR 的封裝,在瀏覽器端使用 XHR,在 Node.js 中使用
http
模塊。 -
優點:
-
基于 Promise,支持
async/await
。 -
自動轉換 JSON 數據。
-
支持請求和響應攔截器。
-
能夠取消請求。
-
-
缺點:
-
需要額外引入庫。
-
在一些極端情況下(如超時控制)可能不如原生 Fetch 靈活。
-
-
使用場景:適用于需要更豐富的功能(如攔截器、自動數據轉換)的場景。
??1.2axios基于 Promise
Axios 的請求返回的是一個 Promise 對象,這使得它能夠很方便地進行異步操作的處理。例如,你可以使用 .then()
方法來處理請求成功的情況,使用 .catch()
方法來處理請求失敗的情況。比如:
axios.get('/user').then(response => {console.log(response.data); // 處理成功響應}).catch(error => {console.error(error); // 處理錯誤});
二、演示get和post
<template><div><h1>Axios GET 和 POST 示例</h1><button @click="fetchData">獲取數據 (GET)</button><button @click="postData">提交數據 (POST)</button><div v-if="data"><h2>獲取的數據:</h2><pre>{{ data }}</pre></div><div v-if="postDataResponse"><h2>POST 請求的響應:</h2><pre>{{ postDataResponse }}</pre></div></div>
</template><script>
import axios from 'axios';export default {data() {return {data: null, // 用于存儲 GET 請求的響應數據postDataResponse: null, // 用于存儲 POST 請求的響應數據};},methods: {// 發起 GET 請求fetchData() {axios.get('https://jsonplaceholder.typicode.com/posts/1').then(response => {this.data = response.data; // 將響應數據存儲到 data 中}).catch(error => {console.error('GET 請求失敗:', error);});},// 發起 POST 請求postData() {const postData = {title: 'foo',body: 'bar',userId: 1,};axios.post('https://jsonplaceholder.typicode.com/posts', postData).then(response => {this.postDataResponse = response.data; // 將響應數據存儲到 postDataResponse 中}).catch(error => {console.error('POST 請求失敗:', error);});},},
};
</script><style>
/* 添加一些簡單的樣式 */
button {margin-right: 10px;
}
</style>
(1)GET
?請求
-
使用
axios.get
方法發起GET
請求。 -
請求的 URL 是
https://jsonplaceholder.typicode.com/posts/1
,這是一個公共的測試 API,返回一個模擬的帖子數據。 -
請求成功后,將響應數據存儲到
data
屬性中,并在頁面上顯示。
(2)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);}},
},
?三、發送帶有請求頭和查詢參數的請求
<template><div><h1>Axios 請求頭和查詢參數示例</h1><button @click="fetchWithHeadersAndParams">發送請求</button><div v-if="response"><h2>響應數據:</h2><pre>{{ response }}</pre></div></div>
</template><script>
import axios from 'axios';export default {data() {return {response: null, // 用于存儲響應數據};},methods: {// 發送帶有請求頭和查詢參數的 GET 請求fetchWithHeadersAndParams() {// 定義請求頭const headers = {'Authorization': 'Bearer your_token_here','Custom-Header': 'CustomValue',};// 定義查詢參數const params = {userId: 1,limit: 10,status: 'active',};// 發起請求axios.get('https://jsonplaceholder.typicode.com/posts', {headers: headers, // 添加請求頭params: params, // 添加查詢參數}).then(response => {this.response = response.data; // 將響應數據存儲到 response 中}).catch(error => {console.error('請求失敗:', error);this.response = { error: error.message }; // 如果失敗,存儲錯誤信息});},},
};
</script><style>
button {margin-right: 10px;
}
</style>
(1)請求頭
-
在
axios.get
方法中,通過headers
屬性傳遞自定義請求頭。 -
示例中添加了
Authorization
和Custom-Header
兩個請求頭。
(2)查詢參數
-
在
axios.get
方法中,通過params
屬性傳遞查詢參數。 -
查詢參數會自動被 Axios 轉換為 URL 的查詢字符串。例如,
params
對象{ userId: 1, limit: 10 }
會被轉換為?userId=1&limit=10
。
(3)完整的請求 URL
假設請求頭和查詢參數都設置好后,最終的請求 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
。
<template><div><h1>Axios 請求體格式示例</h1><button @click="sendUrlEncoded">發送 URL 編碼數據</button><button @click="sendMultipart">發送 Multipart 數據</button><button @click="sendJson">發送 JSON 數據</button><div v-if="response"><h2>響應數據:</h2><pre>{{ response }}</pre></div></div>
</template><script>
import axios from 'axios';export default {data() {return {response: null, // 用于存儲響應數據};},methods: {// 發送 URL 編碼數據sendUrlEncoded() {const data = new URLSearchParams();data.append('username', 'kimi');data.append('password', '123456');axios.post('https://jsonplaceholder.typicode.com/posts', data).then(response => {this.response = response.data;}).catch(error => {console.error('請求失敗:', error);this.response = { error: error.message };});},// 發送 Multipart 數據sendMultipart() {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',},}).then(response => {this.response = response.data;}).catch(error => {console.error('請求失敗:', error);this.response = { error: error.message };});},// 發送 JSON 數據sendJson() {const data = {title: 'foo',body: 'bar',userId: 1,};axios.post('https://jsonplaceholder.typicode.com/posts', data).then(response => {this.response = response.data;}).catch(error => {console.error('請求失敗:', error);this.response = { error: error.message };});},},
};
</script><style>
button {margin-right: 10px;
}
</style>
(1)發送 URL 編碼數據
-
使用
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);
(2)發送 Multipart 數據
-
使用
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',}, });
(3)發送 JSON 數據
-
直接發送一個 JavaScript 對象。
-
Axios 會自動將對象序列化為 JSON 格式,并設置請求頭
Content-Type
為application/json
。 -
示例代碼:
const data = {title: 'foo',body: 'bar',userId: 1, };axios.post('https://jsonplaceholder.typicode.com/posts', data);
五、axios默認配置項
以下是一些常用的 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);
});
1. 全局默認配置
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; // 默認值
};
2. 自定義實例默認配置
除了全局配置,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';
3. 配置的優先級
Axios 的配置會按優先級合并,優先級從低到高依次為:
-
庫默認值:在
lib/defaults.js
中定義的默認值。 -
實例的
defaults
屬性:通過axios.create()
創建的實例的默認配置。 -
請求的
config
參數:在每次請求中傳遞的配置參數。const instance = axios.create({timeout: 2500 // 實例默認超時時間 });instance.get('/longRequest', {timeout: 5000 // 該請求的超時時間覆蓋實例默認值 });
六、axios響應數據的格式和狀態碼
在使用 Axios 發起 HTTP 請求時,響應數據的格式和狀態碼是兩個非常重要的部分。Axios 提供了豐富的響應數據結構,同時允許你根據狀態碼來處理不同的響應情況。?
1. 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);});
2. 狀態碼處理
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);}});
3. 自定義狀態碼處理
你可以通過 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 提供的強大功能,用于在請求發送之前和響應返回之后對數據進行處理。它們可以用于多種場景,例如統一設置請求頭、添加認證信息、處理錯誤、格式化響應數據等。
1. 請求攔截器
請求攔截器可以在請求發送之前對請求進行處理。你可以通過 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);});
2. 響應攔截器
響應攔截器可以在響應返回之后對響應進行處理。你可以通過 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);});
3. 自定義實例的攔截器
除了全局攔截器,你還可以為自定義的 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);});
4. 移除攔截器
如果需要移除某個攔截器,可以通過返回的 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);
5. 使用場景
(1)請求攔截器
-
統一設置請求頭:例如,添加認證信息(如
Authorization
)、內容類型(如Content-Type
)等。 -
添加公共參數:例如,為每個請求添加時間戳或用戶 ID。
-
請求取消:通過
CancelToken
或AbortController
實現請求取消功能。
(2)響應攔截器
-
統一處理響應數據:例如,只返回響應體中的數據部分。
-
統一處理錯誤:例如,根據狀態碼顯示不同的錯誤消息。
-
處理重定向:例如,根據狀態碼(如
401
)跳轉到登錄頁面。