本篇內容主要講解“Axios的核心原理是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Axios的核心原理是什么”吧!
Axios是一個基于promise的HTTP庫,它能夠自動判斷當前環境,自由切換在瀏覽器和 node.js環境中。如果是瀏覽器,就會基于XMLHttpRequests實現;如果是node環境,就會基于node內置核心http模塊實現。同時,它還用promise處理了響應結果,避免陷入回調地獄中去。
不僅如此,Axios還可以攔截請求和響應、轉化請求數據和響應數據、中斷請求、自動轉換JSON數據、客戶端支持防御XSRF等。如此眾多好用的功能,快來一起看看它是如何實現的吧!
1.基本使用
axios基本使用方式主要有:
axios(config)
axios.method(url,data,config)
// 發送 POST 請求 axios({ method: 'post', url: '/user/12345', data: { username: 'Web前端嚴選', age: 2 } }); // GET請求ID參數 axios.get('/user?ID=12345') .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
2.實現axios
從axios(config)的使用上可以看出導出的axios是一個方法,從axios.get()的使用上可以看出導出的axios原型上會有get,post,put,delete等方法。
由分析可知,axios實際上是Axios類中的一個方法。我們可以先寫一個request方法來實現主要的請求功能,這樣就能使用axios(config)形式來調用了。
class Axios{ constructor(){ } request(config){ return new Promise((resolve) => { const {url='',data={},method='get'} = config; //解構傳參 const xhr = new XMLHttpRequest; //創建請求對象 xhr.open(method,url,true); xhr.onreadystatechange = () => { if(xhr.readyState == 4 && xhr.status == 200){ resolve(xhr.responseText); //異步請求返回后將Promise轉為成功態并將結果導出 } } xhr.send(JSON.stringfy(data)); }) } } function CreateAxiosFn(){ let axios = new Axios; let req = axios.request.bind(axios); return req; } let axios = CreateAxiosFn();
然后搭建一個簡易服務端代碼,以測試請求的效果:
const express = require('express') let app = express(); app.all('*', function (req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'Content-Type'); res.header('Access-Control-Allow-Methods', '*'); res.header('Content-Type', 'application/json;charset=utf-8'); next(); }); app.get('/getInfo', function(request, response){ let data = { 'username':'前端嚴選', 'age':'2' }; response.json(data); }); app.listen(3000, function(){ console.log("服務器啟動"); });
啟動服務后,在頁面中測試請求是否成功:
<button onclick="getMsg()">點擊</button> <script src="./axios.js"></script> <script> function getMsg(){ axios({ method: 'get', url: 'http://localhost:3000/getInfo' }).then(res => { console.log(res); }) } </script>
點擊按鈕后,可以看到請求成功并獲取到數據。
3.原型上的方法
接下來實現以axios.method()形式的方法。
通過axios.get(),axios.post(),axios.put()等方法可以看出它們都是Axios.prototype上的方法,這些方法調用內部的request方法即可:
const methodsArr = ['get','post','put','delete','head','options','patch','head']; methodsArr.forEach(method => { Axios.prototype[method] = function(){ return this.request({ method: method, ...arguments[0] }) } })
arguments的第一個參數包含url,data等信息,直接解構它的第一個元素即可
還需要實現一個工具方法,用來將b方法屬性混入到a中去:
const utils = { extend(a,b,context){ for(let key in b){ if(b.hasOwnProperty(key)){ if(typeof b[key] == 'function'){ a[key] = b[key].bind(context); }else{ a[key] = b[key] } } } } }
最終導出axios的request方法,使之擁有get,post等方法
function CreateAxiosFn(){ let axios = new Axios; let req = axios.request.bind(axios); //新增如下代碼 utils.extend(req, Axios.prototype, axios) return req; }
再來測試一下post的請求:
axios.post({ url: 'http://localhost:3000/postTest', data: { a: 1, b: 2 } }).then(res => { console.log(res); })
可以看到正確返回結果了。
4.攔截器
先來看看攔截器的使用:
// 請求攔截 axios.interceptors.request.use(function (config) { // 在發送請求之前 return config; }, function (error) { // 請求錯誤處理 return Promise.reject(error); }); // 響應攔截 axios.interceptors.response.use(function (response) { // 響應數據處理 return response; }, function (error) { // 響應錯誤處理 return Promise.reject(error); });
攔截器,顧名思義就是在請求之前和響應之前,對真正要執行的操作數據攔截住進行一些處理。
那么如何實現呢,首先攔截器也是一個類,用于管理響應和請求。
class InterceptorsManage{ constructor(){ this.handlers = []; } use(onFulField,onRejected){ //將成功的回調和失敗的回調都存放到隊列中 this.handlers.push({ onFulField, onRejected }) } }
axios.interceptors.response.use和axios.interceptors.request.use來定義請求和響應的攔截方法。
這說明axios上有響應攔截器和請求攔截器,那么如何在axios上實現呢:
class Axios{ constructor(){ this.interceptors = { request: new InterceptorsManage, response: new InterceptorsManage } } //.... }
在Axios的構造函數中新增interceptors屬性,然后定義request和response屬性用于處理請求和響應。
執行use方法時,會把傳入的回調函數放到handlers數組中。
這時再回看使用方式,axios.interceptors.request.use方法是綁在axios實例上的,因此同樣需要把Axios上的屬性和方法轉移到request上,將interceptors對象掛載到request方法上。
function CreateAxiosFn() { let axios = new Axios(); let req = axios.request.bind(axios); utils.extend(req, Axios.prototype, axios) //新增如下代碼 utils.extend(req, axios) return req; }
但是現在request不僅要執行請求的發送,還要執行攔截器中handler的回調函數,因此還需要把request方法進行一下改造:
request(config){ //攔截器和請求的隊列 let chain = [this.sendAjax.bind(this),undefined]; //請求的攔截 this.interceptors.request.handlers.forEach(interceptor => { chain.unshift(interceptor.onFulField,interceptor.onRejected); }) //響應的攔截 this.interceptors.response.handlers.forEach(interceptor => { chain.push(interceptor.onFulField,interceptor.onRejected) }) let promise = Promise.resolve(config); while(chain.length > 0){ //從頭部開始依次執行請求的攔截、真正的請求、響應的攔截 promise = promise.then(chain.shift(),chain.shift()); } return promise; } sendAjax(config){ return new Promise((resolve) => { const {url='',method='get',data={}} = config; const xhr = new XMLHttpRequest(); xhr.open(method,url,true); xhr.onreadystatechange = () => { if(xhr.readyState == 4 && xhr.status == 200){ resolve(xhr.responseText) } } xhr.send(JSON.stringify(data)); }) }
最后執行chain的時候是這個樣子的:
chain = [ //請求之前成功的回調和失敗的回調 function (config) { return config; }, function (error) { return Promise.reject(error); } //真正的請求執行 this.sendAjax.bind(this), undefined, //請求之后響應的成功回調和失敗回調 function (response) { return response; }, function (error) { return Promise.reject(error); } ]
請求之前,promise執行為:
promise.then( function (config) { return config; }, function (error) { return Promise.reject(error); } )
請求時,執行為:
promise.then( this.sendAjax.bind(this), undefined, )
響應后,執行為:
promise.then( function (response) { return response; }, function (error) { return Promise.reject(error); } )
這時我們測試一下攔截器的使用:
function getMsg(){ axios.interceptors.request.use((config) => { console.log('請求攔截:',config); return config; },err => { return Promise.reject(err) }) axios.interceptors.response.use(response => { response = { message: '響應數據替換', data: response } return response },err => { console.log(err,'響應錯誤') return Promise.reject(err) }) axios.get({ url: 'http://localhost:3000/getTest', }).then(res => { console.log(res); }) }
可以在控制臺中看到攔截處理的打印輸出,證明攔截成功!
5.總結
Axios天然支持Promise的性能讓其方便對異步進行處理,同時又利用了Promise對請求進行了攔截,使得用戶可以在請求過程中添加更多的功能,對請求的中斷能自如操作。它的思想既清新樸實又不落入俗套,具有很好的借鑒意義。
到此,相信大家對“Axios的核心原理是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。