溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Axios的核心原理是什么

發(fā)布時間:2021-07-22 09:48:18 來源:億速云 閱讀:413 作者:chen 欄目:開發(fā)技術

本篇內(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ù)學習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI