您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“Axios的核心原理是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Axios的核心原理是什么”吧!
Axios是一個基于promise的HTTP庫,它能夠自動判斷當前環(huán)境,自由切換在瀏覽器和 node.js環(huán)境中。如果是瀏覽器,就會基于XMLHttpRequests實現(xiàn);如果是node環(huán)境,就會基于node內(nèi)置核心http模塊實現(xiàn)。同時,它還用promise處理了響應結果,避免陷入回調(diào)地獄中去。
不僅如此,Axios還可以攔截請求和響應、轉(zhuǎn)化請求數(shù)據(jù)和響應數(shù)據(jù)、中斷請求、自動轉(zhuǎn)換JSON數(shù)據(jù)、客戶端支持防御XSRF等。如此眾多好用的功能,快來一起看看它是如何實現(xiàn)的吧!
1.基本使用
axios基本使用方式主要有:
axios(config)
axios.method(url,data,config)
// 發(fā)送 POST 請求 axios({ method: 'post', url: '/user/12345', data: { username: 'Web前端嚴選', age: 2 } }); // GET請求ID參數(shù) axios.get('/user?ID=12345') .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
2.實現(xiàn)axios
從axios(config)的使用上可以看出導出的axios是一個方法,從axios.get()的使用上可以看出導出的axios原型上會有get,post,put,delete等方法。
由分析可知,axios實際上是Axios類中的一個方法。我們可以先寫一個request方法來實現(xiàn)主要的請求功能,這樣就能使用axios(config)形式來調(diào)用了。
class Axios{ constructor(){ } request(config){ return new Promise((resolve) => { const {url='',data={},method='get'} = config; //解構傳參 const xhr = new XMLHttpRequest; //創(chuàng)建請求對象 xhr.open(method,url,true); xhr.onreadystatechange = () => { if(xhr.readyState == 4 && xhr.status == 200){ resolve(xhr.responseText); //異步請求返回后將Promise轉(zhuǎn)為成功態(tài)并將結果導出 } } 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>
點擊按鈕后,可以看到請求成功并獲取到數(shù)據(jù)。
3.原型上的方法
接下來實現(xiàn)以axios.method()形式的方法。
通過axios.get(),axios.post(),axios.put()等方法可以看出它們都是Axios.prototype上的方法,這些方法調(diào)用內(nèi)部的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的第一個參數(shù)包含url,data等信息,直接解構它的第一個元素即可
還需要實現(xiàn)一個工具方法,用來將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) { // 在發(fā)送請求之前 return config; }, function (error) { // 請求錯誤處理 return Promise.reject(error); }); // 響應攔截 axios.interceptors.response.use(function (response) { // 響應數(shù)據(jù)處理 return response; }, function (error) { // 響應錯誤處理 return Promise.reject(error); });
攔截器,顧名思義就是在請求之前和響應之前,對真正要執(zhí)行的操作數(shù)據(jù)攔截住進行一些處理。
那么如何實現(xiàn)呢,首先攔截器也是一個類,用于管理響應和請求。
class InterceptorsManage{ constructor(){ this.handlers = []; } use(onFulField,onRejected){ //將成功的回調(diào)和失敗的回調(diào)都存放到隊列中 this.handlers.push({ onFulField, onRejected }) } }
axios.interceptors.response.use和axios.interceptors.request.use來定義請求和響應的攔截方法。
這說明axios上有響應攔截器和請求攔截器,那么如何在axios上實現(xiàn)呢:
class Axios{ constructor(){ this.interceptors = { request: new InterceptorsManage, response: new InterceptorsManage } } //.... }
在Axios的構造函數(shù)中新增interceptors屬性,然后定義request和response屬性用于處理請求和響應。
執(zhí)行use方法時,會把傳入的回調(diào)函數(shù)放到handlers數(shù)組中。
這時再回看使用方式,axios.interceptors.request.use方法是綁在axios實例上的,因此同樣需要把Axios上的屬性和方法轉(zhuǎn)移到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; }
但是現(xiàn)在request不僅要執(zhí)行請求的發(fā)送,還要執(zhí)行攔截器中handler的回調(diào)函數(shù),因此還需要把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){ //從頭部開始依次執(zhí)行請求的攔截、真正的請求、響應的攔截 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)); }) }
最后執(zhí)行chain的時候是這個樣子的:
chain = [ //請求之前成功的回調(diào)和失敗的回調(diào) function (config) { return config; }, function (error) { return Promise.reject(error); } //真正的請求執(zhí)行 this.sendAjax.bind(this), undefined, //請求之后響應的成功回調(diào)和失敗回調(diào) function (response) { return response; }, function (error) { return Promise.reject(error); } ]
請求之前,promise執(zhí)行為:
promise.then( function (config) { return config; }, function (error) { return Promise.reject(error); } )
請求時,執(zhí)行為:
promise.then( this.sendAjax.bind(this), undefined, )
響應后,執(zhí)行為:
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: '響應數(shù)據(jù)替換', 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的核心原理是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關內(nèi)容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。