Axios 如何緩存請求數據?

大家好,我是若川。歡迎加我微信?ruochuan12,長期交流學習。今天推薦這篇Axios緩存請求數據的文章,相信是常見的業務場景,感興趣的讀者可以看看 umi-request,支持緩存功能。另外我之前也寫過 axios源碼文章,是轉載次數(16次)最多的一篇文章,好久沒寫好文章了,慚愧慚愧。

點擊下方卡片關注我,或者查看源碼等系列文章。學習源碼整體架構系列、年度總結、JS基礎系列

在 Axios 如何取消重復請求? 這篇文章中,阿寶哥介紹了在 Axios 中如何取消重復請求及 CancelToken 的工作原理。本文將介紹在 Axios 中如何通過增強默認適配器來緩存請求數據。那么為什么要緩存請求數據呢?這是因為在緩存未失效時,我們可以直接使用已緩存的數據,而不需發起請求從服務端獲取數據,這樣不僅可以減少 HTTP 請求而且還能減少等待時間從而提高用戶體驗。

因為本文將使用 Axios 提供的默認適配器來實現緩存請求數據的功能,所以如果你對 Axios 適配器還不熟悉的話,建議先閱讀 77.9K 的 Axios 項目有哪些值得借鑒的地方 這篇文章。為了讓大家能夠更好地理解后續的內容,我們先來看一下整體的流程圖:

上圖中藍色部分的工作流程,就是本文的重點。接下來,阿寶哥將從如何設計緩存開始,帶大家一起來開發緩存請求數據的功能。

一、如何設計緩存

在計算中,緩存是一個高速數據存儲層,其中存儲了數據子集,且通常是 短暫性 存儲,這樣日后再次請求該數據時,速度要比訪問數據的主存儲位置快。通過緩存,你可以高效地重用之前檢索或計算的數據。了解完緩存的作用之后,我們來設計緩存的 API:

  • get(key):從緩存中獲取指定 key 對應的值;

  • delete(key):從緩存中刪除指定 key 對應的值;

  • clear():清空已緩存的數據;

  • set(key, value, maxAge):保存鍵值對,同時支持設置緩存的最大時間,即 maxAge 單位為毫秒。

基于上述的緩存 API,我們可以實現一個簡單的緩存功能,具體代碼如下所示:

const?MemoryCache?=?{data:?{},set(key,?value,?maxAge)?{?//?保存數據this.data[key]?=?{maxAge:?maxAge?||?0,value,now:?Date.now(),};},get(key)?{?//?從緩存中獲取指定 key 對應的值。const?cachedItem?=?this.data[key];if?(!cachedItem)?return?null;const?isExpired?=?Date.now()?-?cachedItem.now?>?cachedItem.maxAge;isExpired?&&?this.delete(key);return?isExpired???null?:?cachedItem.value;},delete(key)?{?//?從緩存中刪除指定 key 對應的值。return?delete?this.data[key];},clear()?{?//?清空已緩存的數據。this.data?=?{};},
};

其實除了自定義緩存對象之外,你也可以使用成熟的第三方庫,比如 lru-cache。

LRU 緩存淘汰算法就是一種常用策略。LRU 的全稱是 Least Recently Used,也就是說我們認為最近使用過的數據應該是是「有用的」,很久都沒用過的數據應該是無用的,內存滿了就優先刪那些很久沒用過的數據。

二、如何增強默認適配器

Axios 引入了適配器,使得它可以同時支持瀏覽器和 Node.js 環境。對于瀏覽器環境來說,它通過封裝 XMLHttpRequest API 來發送 HTTP 請求,而對于 Node.js 環境來說,它通過封裝 Node.js 內置的 http?和?https 模塊來發送 HTTP 請求。

在介紹如何增強默認適配器之前,我們先來回顧一下 Axios 完整請求的流程:

了解完 Axios 完整請求的流程之后,我們再來看一下 Axios 內置的 xhrAdapter 適配器,它被定義在 lib/adapters/xhr.js 文件中:

//?lib/adapters/xhr.js
module.exports?=?function?xhrAdapter(config)?{return?new?Promise(function?dispatchXhrRequest(resolve,?reject)?{var?requestData?=?config.data;var?requestHeaders?=?config.headers;var?request?=?new?XMLHttpRequest();//?省略大部分代碼var?fullPath?=?buildFullPath(config.baseURL,?config.url);request.open(config.method.toUpperCase(),?buildURL(fullPath,?config.params,?config.paramsSerializer),?true);//?Set?the?request?timeout?in?MSrequest.timeout?=?config.timeout;//?Listen?for?ready?staterequest.onreadystatechange?=?function?handleLoad()?{?...?}//?Send?the?requestrequest.send(requestData);});
};

很明顯 xhrAdapter 適配器是一個函數對象,它接收一個 config 參數并返回一個 Promise 對象。而在 xhrAdapter 適配器內部,最終會使用 XMLHttpRequest API 來發送 HTTP 請求。為了實現緩存請求數據的功能,我們就可以考慮通過高階函數來增強 xhrAdapter 適配器的功能。

2.1 定義輔助函數

2.1.1 定義 generateReqKey 函數

在增強 xhrAdapter 適配器之前,我們先來定義一個 generateReqKey 函數,該函數用于根據當前請求的信息,生成請求 Key;

function?generateReqKey(config)?{const?{?method,?url,?params,?data?}?=?config;return?[method,?url,?Qs.stringify(params),?Qs.stringify(data)].join("&");
}

通過 generateReqKey 函數生成的請求 key,將作為緩存項的 key,而對應的 value 就是默認 xhrAdapter 適配器返回的 Promise 對象。

2.1.2 定義 isCacheLike 函數

isCacheLike 函數用于判斷傳入的 cache 參數是否實現了前面定義的 Cache API,利用該函數,我們允許用戶為每個請求自定義 Cache 對象。

function?isCacheLike(cache)?{return?!!(cache.set?&&?cache.get?&&?cache.delete?&&?cache.clear??&&?typeof?cache.get?===?'function'?&&?typeof?cache.set?===?'function'?&&?typeof?cache.delete?===?'function'?&&?typeof?cache.clear?===?'function');
}

2.2 定義 cacheAdapterEnhancer 函數

為了讓用戶能夠更靈活地控制數據緩存的功能,我們定義了一個 cacheAdapterEnhancer 函數,該函數支持兩個參數:

  • adapter:預增強的 Axios 適配器對象;

  • options:緩存配置對象,該對象支持 4 個屬性,分別用于配置不同的功能:

    • maxAge:全局設置緩存的最大時間;

    • enabledByDefault:是否啟用緩存,默認為 true;

    • cacheFlag:緩存標志,用于配置請求 config 對象上的緩存屬性;

    • defaultCache:用于設置使用的緩存對象。

了解完 cacheAdapterEnhancer 函數的參數之后,我們來看一下該函數的具體實現:

function?cacheAdapterEnhancer(adapter,?options)?{const?{?maxAge,?enabledByDefault?=?true,cacheFlag?=?"cache",?defaultCache?=?MemoryCache,}?=?options;return?(config)?=>?{const?{?url,?method,?params,?forceUpdate?}?=?config;let?useCache?=?config[cacheFlag]?!==?undefined?&&?config[cacheFlag]?!==?null??config[cacheFlag]:?enabledByDefault;if?(method?===?"get"?&&?useCache)?{const?cache?=?isCacheLike(useCache)???useCache?:?defaultCache;let?requestKey?=?generateReqKey(config);??//?生成請求Keylet?responsePromise?=?cache.get(requestKey);?//?從緩存中獲取請求key對應的響應對象if?(!responsePromise?||?forceUpdate)?{?//?緩存未命中/失效或強制更新時,則重新請求數據responsePromise?=?(async?()?=>?{try?{return?await?adapter(config);??//?使用默認的xhrAdapter發送請求}?catch?(reason)?{cache.delete(requestKey);throw?reason;}})();cache.set(requestKey,?responsePromise,?maxAge);??//?保存請求返回的響應對象return?responsePromise;?//?返回已保存的響應對象}return?responsePromise;}return?adapter(config);?//?使用默認的xhrAdapter發送請求};
}

以上的代碼并不會復雜,核心的處理邏輯如下圖所示:

2.3 使用 cacheAdapterEnhancer 函數

2.3.1 創建 Axios 對象并配置 adapter 選項
const?http?=?axios.create({baseURL:?"https://jsonplaceholder.typicode.com",adapter:?cacheAdapterEnhancer(axios.defaults.adapter,?{enabledByDefault:?false,?//?默認禁用緩存maxAge:?5000,?//?緩存時間為5s}),
});
2.3.2 使用 http 對象發送請求
//?使用緩存
async?function?requestWithCache()?{const?response?=?await?http.get("/todos/1",?{?cache:?true?});console.dir(response);
}//?不使用緩存
async?function?requestWithoutCache()?{const?response?=?await?http.get("/todos/1",?{?cache:?false?});console.dir(response);
}

其實 cache 屬性除了支持布爾值之外,我們可以配置實現 Cache API 的緩存對象,具體的使用示例如下所示:

const?customCache?=?{?get()?{/*...*/},?set()?{/*...*/},?delete()?{/*...*/},?clear()?{/*...*/}};async?function?requestForceUpdate()?{const?response?=?await?http.get("/todos/1",?{cache:?customCache,forceUpdate:?true,});console.dir(response);
}

好了,如何通過增強 xhrAdapter 適配器來實現 Axios 緩存請求數據的功能已經介紹完了。由于完整的示例代碼內容比較多,阿寶哥就不放具體的代碼了。感興趣的小伙伴,可以訪問以下地址瀏覽示例代碼。

完整的示例代碼:https://gist.github.com/semlinker/b8a7bd5a0a16c2d04011c2c4a8167fbd

三、總結

本文介紹了在 Axios 中如何緩存請求數據及如何設計緩存對象,基于文中定義的 cacheAdapterEnhancer 函數,你可以輕松地擴展緩存的功能。在后續的文章中,阿寶哥將會介紹在 Axios 中如何實現請求重試功能,感興趣的小伙伴不要錯過喲。另外,如果你對 Axios 如何取消重復請求感興趣,可以閱讀 Axios 如何取消重復請求? 這篇文章。

四、參考資源

  • 77.9K 的 Axios 項目有哪些值得借鑒的地方

  • Axios 如何取消重復請求?

  • Github - axios-extensions


最近組建了一個江西人的前端交流群,如果你也是江西人可以加我微信 ruochuan12 拉你進群。


·················?若川出品?·················

今日話題

建的江西前端交流群,感覺氛圍不錯,想著要不要建其他省份的交流群,不過我是江西人,建其他省份的會不會有人進群是個問題~。歡迎分享、收藏、點贊、在看我的公眾號文章~

一個愿景是幫助5年內前端人走向前列的公眾號

可加我個人微信 ruochuan12,長期交流學習

推薦閱讀

我在阿里招前端,我該怎么幫你?(現在還能加我進模擬面試群)

如何拿下阿里巴巴 P6 的前端 Offer

點擊方卡片關注我,或者查看源碼等系列文章。
學習源碼整體架構系列、年度總結、JS基礎系列

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/news/275992.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/275992.shtml
英文地址,請注明出處:http://en.pswp.cn/news/275992.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Reflection in .net

最近在看設計模式的一些東西,在講到builder模式中使用到了c#的反射機制,從網上找了寫資料,整理如下: 在C#中,我們要使用反射,首先要搞清楚以下命名空間中幾個類的關系: System.Reflection命名空間(1) App…

山西萬榮盛裝迎新春 首屆群眾文化藝術節啟幕

山西萬榮盛裝迎新春,首屆群眾文化藝術節啟幕。 李繼旺 攝 山西萬榮盛裝迎新春,首屆群眾文化藝術節啟幕。 李繼旺 攝 中新網太原1月29日電 (任麗娜)璀璨閃耀的寶鼎廣場花燈展、激情活力的群眾文體賽事、精彩紛呈的紅火熱鬧、精品年貨展銷、李家大院游園會…

MySQL 隱式轉換 字符串和整型說明

MySQL 隱式轉換 字段類型定義 CREATE TABLE user (id int(10) NOT NULL AUTO_INCREMENT COMMENT 編號,/* ...... */name varchar(10) NOT NULL DEFAULT COMMENT 姓名,/* ...... */PRIMARY KEY (id),KEY idx_name (name,nickname),/* ...... */ ) ENGINEInnoDB DEFAULT CHARSE…

安裝vs2017出現閃退現象_Adobe Reader 閃退

在我們的日常辦公、學習中經常會涉及到 PDF 文件,免不了需要處理 PDF 文件如:PDF轉Word、PDF合并、導出成圖片、PDF解密、PDF轉PPT、PDF加水印、PDF簽名等等。PDF是與平臺無關的文件格式,無論在哪種打印機上都可保證精確的顏色和準確的打印效…

從Vue.js源碼中我學到的幾個實用函數

大家好,我是若川。歡迎加我微信 ruochuan12,長期交流學習。今天推薦Vuejs源碼中幾個實用的方法。如果想看Vuejs源碼,不知道如何下手,一般推薦配置Sourcemap,針對單個問題調試來看,如何調試Vuejs源碼&#x…

real類型_如何使用REAL方法對您的Web內容進行現實檢查

real類型Web內容審核模板 (Web content audit template) I recently completed a website audit project for a nonprofit organization through CatchAFire.org. As part of the website audit, I audited every key page’s content, looking for areas of opportunity.我最近…

青海行--(7月26日)翻越祁連山

嘉峪關是最值得一寫的,雖然也是著名的旅游城嘉峪關景點是國家AAAAA級景區,但與敦煌完全不一樣,沒有人山人海的游客,門票也不貴,才10&a…

TikTok真題第1天 | 666.路徑和IV、 207.課程表、210.課程表||

666.路徑和IV 題目鏈接:666.路徑和IV 解法: 參考這篇題解:【LeetCode - 666】路徑和 IV_力扣666路徑總和4-CSDN博客 關鍵點在于: (1)使用map來存node:key 為整數的前兩位,value…

導出Excel

2019獨角獸企業重金招聘Python工程師標準>>> 思路: 1, 引入Excel類庫; 2, 創建一個模板; 3, 將數據填充進去; 4, 生成文件; 下面是一個簡單的示例 $phpExcelObj new PHPExcel(); $titleMap self::TITLE_MAP; //設置表頭 $i 0; foreach ($titleMap as $key > $…

CentOS系統更換yum源(repomd.xml not found解決方案)

CentOS系統更換yum源 問題 當初瞎鼓搗服務器,更換yum源為aliyun的,奈何阿里的源最近全部打不開,導致yum安裝不了,一直報錯: http://mirrors.aliyun.com/centos/6/os/x86_64/repodata/repomd.xml: [Errno 14] PYCURL E…

在類中用class時數據是共有還是私有_jvm學習筆記之class文件的加載、初始化

編寫的java文件在要真正運行時,會首先被編譯成 “.class"結尾的二進制文件,然后被虛擬機加載。那么在虛擬機中一個class文件要成為java實例,需要經歷好幾個步驟:1、裝載:裝載階段由三個基本動作完成,要…

所有前端都要看的2D游戲化互動入門基礎知識

背景現在越來越多的公司和APP開始使用游戲化的方式去做產品了,所謂游戲化,是指在非游戲環境中將游戲的思維和游戲的機制進行整合運用,以引導用戶互動和使用的方法。支付寶里面的螞蟻莊園、螞蟻森林,通過游戲和公益的結合實現用戶的…

江蘇一動物園現“旋轉活馬” 園方:創意來自馬術訓練

中新網南通1月31日電 (記者唐娟)“旋轉馬設備采用同時容納六匹馬的遛馬器組裝而成,對馬匹沒有任何傷害,初衷是希望給小朋友一種全新體驗,這才有了這個創意項目。”1月31日,針對活馬版“旋轉木馬”引發的熱議,江蘇南通森…

Byte數組轉換成string 的方法積累

.net的加密算法,返回的都是byte[] 類型,在存貯起來讓人非常頭疼,最簡單的方法就是把byte[]轉換成string來存貯,當然如果數據量大的話,另當別論。 所以我就把byte[]轉換成string的方法做一個簡單的積累與分析。目前有3種…

加快信息化建設對地方發展的_加快設計師職業發展的9種方法

加快信息化建設對地方發展的重點 (Top highlight)Over the past few months, I have had an increase in conversations with design students from various institutions, as well as early, to senior-level designers, researchers, & product managers from various co…

Docker:Nginx-Redis-Mysql-PHP 部署

Docker:Nginx-Redis-Mysql-PHP 部署 網絡橋接 Docker容器之間默認網絡隔離,需要使用橋接網絡進行互通 創建網絡 docker network create net-local docker network ls NETWORK ID NAME DRIVER SCOPE da9c8fc3dc80 bridge bridge local 78641…

epoll監聽文件_介紹一下 Android Handler 中的 epoll 機制?

介紹一下 Android Handler 中的 epoll 機制?目錄:IO 多路復用select、poll、epoll 對比epoll APIepoll 使用示例Handler 中的 epoll 源碼分析IO 多路復用IO 多路復用是一種同步 IO 模型,實現一個線程可以監視多個文件句柄。一旦某個文件句柄就…

前端工程師的一大神器——puppeteer

大家好,我是若川。歡迎加我微信 ruochuan12,長期交流學習。今天推薦神器puppeteer,我猜有挺多人不知道。文章不長,看完有空也可以試玩。我18年也寫過一篇puppeteer爬取生成pdf的文章,時間真快。前端使用puppeteer 爬蟲…

selenium界面元素定位

一、 Selenium界面元素定位 本文元素定位以das2為例 #導入包 from selenium import webdriver #打開火狐驅動 driverwebdriver.Firefox() #訪問網址 driver.get("http://192.168.3.217:8080/das/seatlogin.jsp ") 進行web頁面自動化測試,對頁面上…

vue.js ui_UI / UX開發:考慮Vue.js

vue.js uiBecause sometimes we have to add logic to our concepts, and Vue makes it a whole lot easier.因為有時我們必須在概念中添加邏輯,而Vue使其變得更加容易。 FULL DISCLOSURE: THIS IS NOT A COMPLETE JAVASCRIPT OR VUE COURSE. There’s no way I co…