自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Axios 如何緩存請(qǐng)求數(shù)據(jù)?

存儲(chǔ) 存儲(chǔ)軟件
本文將介紹在 Axios 中如何通過(guò)增強(qiáng)默認(rèn)適配器來(lái)緩存請(qǐng)求數(shù)據(jù)。

[[392358]]

本文轉(zhuǎn)載自微信公眾號(hào)「全棧修仙之路」,作者阿寶哥。轉(zhuǎn)載本文請(qǐng)聯(lián)系全棧修仙之路公眾號(hào)。  

在 Axios 如何取消重復(fù)請(qǐng)求? 這篇文章中,阿寶哥介紹了在 Axios 中如何取消重復(fù)請(qǐng)求及 CancelToken 的工作原理。本文將介紹在 Axios 中如何通過(guò)增強(qiáng)默認(rèn)適配器來(lái)緩存請(qǐng)求數(shù)據(jù)。那么為什么要緩存請(qǐng)求數(shù)據(jù)呢?這是因?yàn)樵诰彺嫖词r(shí),我們可以直接使用已緩存的數(shù)據(jù),而不需發(fā)起請(qǐng)求從服務(wù)端獲取數(shù)據(jù),這樣不僅可以減少 HTTP 請(qǐng)求而且還能減少等待時(shí)間從而提高用戶體驗(yàn)。

因?yàn)楸疚膶⑹褂?Axios 提供的默認(rèn)適配器來(lái)實(shí)現(xiàn)緩存請(qǐng)求數(shù)據(jù)的功能,所以如果你對(duì) Axios 適配器還不熟悉的話,建議先閱讀 77.9K 的 Axios 項(xiàng)目有哪些值得借鑒的地方 這篇文章。為了讓大家能夠更好地理解后續(xù)的內(nèi)容,我們先來(lái)看一下整體的流程圖:

上圖中藍(lán)色部分的工作流程,就是本文的重點(diǎn)。接下來(lái),阿寶哥將從如何設(shè)計(jì)緩存開(kāi)始,帶大家一起來(lái)開(kāi)發(fā)緩存請(qǐng)求數(shù)據(jù)的功能。

一、如何設(shè)計(jì)緩存

在計(jì)算中,緩存是一個(gè)高速數(shù)據(jù)存儲(chǔ)層,其中存儲(chǔ)了數(shù)據(jù)子集,且通常是 短暫性 存儲(chǔ),這樣日后再次請(qǐng)求該數(shù)據(jù)時(shí),速度要比訪問(wèn)數(shù)據(jù)的主存儲(chǔ)位置快。通過(guò)緩存,你可以高效地重用之前檢索或計(jì)算的數(shù)據(jù)。了解完緩存的作用之后,我們來(lái)設(shè)計(jì)緩存的 API:

  • get(key):從緩存中獲取指定 key 對(duì)應(yīng)的值;
  • delete(key):從緩存中刪除指定 key 對(duì)應(yīng)的值;
  • clear():清空已緩存的數(shù)據(jù);
  • set(key, value, maxAge):保存鍵值對(duì),同時(shí)支持設(shè)置緩存的最大時(shí)間,即 maxAge 單位為毫秒。

基于上述的緩存 API,我們可以實(shí)現(xiàn)一個(gè)簡(jiǎn)單的緩存功能,具體代碼如下所示:

  1. const MemoryCache = { 
  2.   data: {}, 
  3.   set(key, value, maxAge) { // 保存數(shù)據(jù) 
  4.     this.data[key] = { 
  5.       maxAge: maxAge || 0, 
  6.       value, 
  7.       now: Date.now(), 
  8.      }; 
  9.   }, 
  10.   get(key) { // 從緩存中獲取指定 key 對(duì)應(yīng)的值。 
  11.     const cachedItem = this.data[key]; 
  12.     if (!cachedItem) return null
  13.     const isExpired = Date.now() - cachedItem.now > cachedItem.maxAge; 
  14.     isExpired && this.delete(key); 
  15.     return isExpired ? null : cachedItem.value; 
  16.   }, 
  17.   delete(key) { // 從緩存中刪除指定 key 對(duì)應(yīng)的值。 
  18.     return delete this.data[key]; 
  19.   }, 
  20.   clear() { // 清空已緩存的數(shù)據(jù)。 
  21.     this.data = {}; 
  22.   }, 
  23. }; 

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

LRU 緩存淘汰算法就是一種常用策略。LRU 的全稱是 Least Recently Used,也就是說(shuō)我們認(rèn)為最近使用過(guò)的數(shù)據(jù)應(yīng)該是是「有用的」,很久都沒(méi)用過(guò)的數(shù)據(jù)應(yīng)該是無(wú)用的,內(nèi)存滿了就優(yōu)先刪那些很久沒(méi)用過(guò)的數(shù)據(jù)。

二、如何增強(qiáng)默認(rèn)適配器

Axios 引入了適配器,使得它可以同時(shí)支持瀏覽器和 Node.js 環(huán)境。對(duì)于瀏覽器環(huán)境來(lái)說(shuō),它通過(guò)封裝 XMLHttpRequest API 來(lái)發(fā)送 HTTP 請(qǐng)求,而對(duì)于 Node.js 環(huán)境來(lái)說(shuō),它通過(guò)封裝 Node.js 內(nèi)置的 http 和 https 模塊來(lái)發(fā)送 HTTP 請(qǐng)求。

在介紹如何增強(qiáng)默認(rèn)適配器之前,我們先來(lái)回顧一下 Axios 完整請(qǐng)求的流程:

了解完 Axios 完整請(qǐng)求的流程之后,我們?cè)賮?lái)看一下 Axios 內(nèi)置的 xhrAdapter 適配器,它被定義在 lib/adapters/xhr.js 文件中:

  1. // lib/adapters/xhr.js 
  2. module.exports = function xhrAdapter(config) { 
  3.   return new Promise(function dispatchXhrRequest(resolve, reject) { 
  4.     var requestData = config.data; 
  5.     var requestHeaders = config.headers; 
  6.  
  7.     var request = new XMLHttpRequest(); 
  8.     // 省略大部分代碼 
  9.     var fullPath = buildFullPath(config.baseURL, config.url); 
  10.     request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true); 
  11.     // Set the request timeout in MS 
  12.     request.timeout = config.timeout; 
  13.  
  14.     // Listen for ready state 
  15.     request.onreadystatechange = function handleLoad() { ... } 
  16.  
  17.     // Send the request 
  18.     request.send(requestData); 
  19.   }); 
  20. }; 

很明顯 xhrAdapter 適配器是一個(gè)函數(shù)對(duì)象,它接收一個(gè) config 參數(shù)并返回一個(gè) Promise 對(duì)象。而在 xhrAdapter 適配器內(nèi)部,最終會(huì)使用 XMLHttpRequest API 來(lái)發(fā)送 HTTP 請(qǐng)求。為了實(shí)現(xiàn)緩存請(qǐng)求數(shù)據(jù)的功能,我們就可以考慮通過(guò)高階函數(shù)來(lái)增強(qiáng) xhrAdapter 適配器的功能。

2.1 定義輔助函數(shù)

2.1.1 定義 generateReqKey 函數(shù)

在增強(qiáng) xhrAdapter 適配器之前,我們先來(lái)定義一個(gè) generateReqKey 函數(shù),該函數(shù)用于根據(jù)當(dāng)前請(qǐng)求的信息,生成請(qǐng)求 Key;

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

通過(guò) generateReqKey 函數(shù)生成的請(qǐng)求 key,將作為緩存項(xiàng)的 key,而對(duì)應(yīng)的 value 就是默認(rèn) xhrAdapter 適配器返回的 Promise 對(duì)象。

2.1.2 定義 isCacheLike 函數(shù)

isCacheLike 函數(shù)用于判斷傳入的 cache 參數(shù)是否實(shí)現(xiàn)了前面定義的 Cache API,利用該函數(shù),我們?cè)试S用戶為每個(gè)請(qǐng)求自定義 Cache 對(duì)象。

  1. function isCacheLike(cache) { 
  2.  return !!(cache.set && cache.get && cache.delete && cache.clear   
  3.   && typeof cache.get === 'function' && typeof cache.set === 'function'  
  4.     && typeof cache.delete === 'function' && typeof cache.clear === 'function' 
  5.   ); 

2.2 定義 cacheAdapterEnhancer 函數(shù)

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

adapter:預(yù)增強(qiáng)的 Axios 適配器對(duì)象;

options:緩存配置對(duì)象,該對(duì)象支持 4 個(gè)屬性,分別用于配置不同的功能:

maxAge:全局設(shè)置緩存的最大時(shí)間;

enabledByDefault:是否啟用緩存,默認(rèn)為 true;

cacheFlag:緩存標(biāo)志,用于配置請(qǐng)求 config 對(duì)象上的緩存屬性;

defaultCache:用于設(shè)置使用的緩存對(duì)象。

了解完 cacheAdapterEnhancer 函數(shù)的參數(shù)之后,我們來(lái)看一下該函數(shù)的具體實(shí)現(xiàn):

  1. function cacheAdapterEnhancer(adapter, options) { 
  2.   const { maxAge, enabledByDefault = true
  3.     cacheFlag = "cache", defaultCache = MemoryCache, 
  4.   } = options; 
  5.    
  6.   return (config) => { 
  7.     const { url, method, params, forceUpdate } = config; 
  8.     let useCache = config[cacheFlag] !== undefined && config[cacheFlag] !== null 
  9.         ? config[cacheFlag] 
  10.         : enabledByDefault; 
  11.       if (method === "get" && useCache) { 
  12.         const cache = isCacheLike(useCache) ? useCache : defaultCache; 
  13.         let requestKey = generateReqKey(config);  // 生成請(qǐng)求Key 
  14.         let responsePromise = cache.get(requestKey); // 從緩存中獲取請(qǐng)求key對(duì)應(yīng)的響應(yīng)對(duì)象 
  15.         if (!responsePromise || forceUpdate) { // 緩存未命中/失效或強(qiáng)制更新時(shí),則重新請(qǐng)求數(shù)據(jù) 
  16.            responsePromise = (async () => { 
  17.              try { 
  18.                return await adapter(config);  // 使用默認(rèn)的xhrAdapter發(fā)送請(qǐng)求 
  19.              } catch (reason) { 
  20.                  cache.delete(requestKey); 
  21.                  throw reason; 
  22.                 } 
  23.            })(); 
  24.            cache.set(requestKey, responsePromise, maxAge);  // 保存請(qǐng)求返回的響應(yīng)對(duì)象 
  25.            return responsePromise; // 返回已保存的響應(yīng)對(duì)象 
  26.        } 
  27.        return responsePromise; 
  28.      } 
  29.      return adapter(config); // 使用默認(rèn)的xhrAdapter發(fā)送請(qǐng)求 
  30.    }; 

以上的代碼并不會(huì)復(fù)雜,核心的處理邏輯如下圖所示:

2.3 使用 cacheAdapterEnhancer 函數(shù)

2.3.1 創(chuàng)建 Axios 對(duì)象并配置 adapter 選項(xiàng)

  1. const http = axios.create({ 
  2.   baseURL: "https://jsonplaceholder.typicode.com"
  3.   adapter: cacheAdapterEnhancer(axios.defaults.adapter, { 
  4.     enabledByDefault: false, // 默認(rèn)禁用緩存 
  5.     maxAge: 5000, // 緩存時(shí)間為5s 
  6.   }), 
  7. }); 

2.3.2 使用 http 對(duì)象發(fā)送請(qǐng)求

  1. // 使用緩存 
  2. async function requestWithCache() { 
  3.   const response = await http.get("/todos/1", { cache: true }); 
  4.   console.dir(response); 
  5.  
  6. // 不使用緩存 
  7. async function requestWithoutCache() { 
  8.   const response = await http.get("/todos/1", { cache: false }); 
  9.   console.dir(response); 

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

  1. const customCache = { get() {/*...*/}, set() {/*...*/}, delete() {/*...*/}, clear() {/*...*/}}; 
  2.        
  3. async function requestForceUpdate() { 
  4.   const response = await http.get("/todos/1", { 
  5.     cache: customCache, 
  6.     forceUpdate: true
  7.   }); 
  8.   console.dir(response); 

好了,如何通過(guò)增強(qiáng) xhrAdapter 適配器來(lái)實(shí)現(xiàn) Axios 緩存請(qǐng)求數(shù)據(jù)的功能已經(jīng)介紹完了。由于完整的示例代碼內(nèi)容比較多,阿寶哥就不放具體的代碼了。感興趣的小伙伴,可以訪問(wèn)以下地址瀏覽示例代碼。

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

三、總結(jié)

本文介紹了在 Axios 中如何緩存請(qǐng)求數(shù)據(jù)及如何設(shè)計(jì)緩存對(duì)象,基于文中定義的 cacheAdapterEnhancer 函數(shù),你可以輕松地?cái)U(kuò)展緩存的功能。在后續(xù)的文章中,阿寶哥將會(huì)介紹在 Axios 中如何實(shí)現(xiàn)請(qǐng)求重試功能,感興趣的小伙伴不要錯(cuò)過(guò)喲。

 

責(zé)任編輯:武曉燕 來(lái)源: 全棧修仙之路
相關(guān)推薦

2020-10-20 09:51:51

Vue 3 的組合

2020-10-20 09:30:13

Vue 3 API 數(shù)據(jù)

2021-03-27 22:21:48

HTTPPython數(shù)據(jù)

2021-04-22 05:37:14

Axios 開(kāi)源項(xiàng)目HTTP 攔截器

2011-04-21 09:59:48

WEBjavascript

2021-04-06 06:01:11

AxiosWeb 項(xiàng)目開(kāi)發(fā)

2021-07-27 14:50:15

axiosHTTP前端

2024-08-27 08:55:32

Axios底層網(wǎng)絡(luò)

2019-07-30 11:17:18

系統(tǒng)數(shù)據(jù)安全

2024-08-12 12:32:53

Axios機(jī)制網(wǎng)絡(luò)

2024-06-05 08:42:24

2022-02-15 08:51:21

AjaxFetchAxios

2013-08-20 13:22:35

PythonGo編程語(yǔ)言

2021-10-08 10:05:10

數(shù)據(jù)包三次握手HTTP

2020-11-09 11:10:56

前端api緩存

2021-05-19 09:29:52

VueAxios異步請(qǐng)求

2022-07-03 20:53:23

React18請(qǐng)求數(shù)據(jù)

2018-03-28 09:26:43

數(shù)據(jù)庫(kù)緩存層優(yōu)化

2018-07-30 16:31:00

javascriptaxioshttp

2019-09-11 10:55:16

網(wǎng)絡(luò)入職數(shù)據(jù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)