前端 api 請求快取方案

2021-09-19 22:53:19 字數 4799 閱讀 2769

在開發 web 應用程式時,效能都是必不可少的話題。對於webpack打包的單頁面應用程式而言,我們可以採用很多方式來對效能進行優化,比方說 tree-shaking、模組懶載入、利用 extrens 網路cdn 加速這些常規的優化。甚至在vue-cli 專案中我們可以使用 --modern 指令生成新舊兩份瀏覽器**來對程式進行優化。

而事實上,快取一定是提公升web應用程式有效方法之一,尤其是使用者受限於網速的情況下。提公升系統的響應能力,降低網路的消耗。當然,內容越接近於使用者,則快取的速度就會越快,快取的有效性則會越高。

以客戶端而言,我們有很多快取資料與資源的方法,例如 標準的瀏覽器快取 以及 目前火熱的 service worker。但是,他們更適合靜態內容的快取。例如 html,js,css以及等檔案。而快取系統資料,我採用另外的方案。

那我現在就對我應用到專案中的各種 api 請求快取方案,從簡單到複雜依次介紹一下。

簡單的 資料 快取,第一次請求時候獲取資料,之後便使用資料,不再請求後端api。

**如下:

const datacache = new map()

async getwares()

return data

}

第一行** 使用了 es6以上的 map,如果對map不是很理解的情況下,你可以參考 ecmascript 6 入門 set 和 map或者 exploring es6 關於 map 和 set的介紹,此處可以理解為乙個鍵值對儲存結構。

之後 ** 使用 了 async 函式,可以將非同步操作變得更為方便。 你可以參考ecmascript 6 入門 async函式來進行學習或者鞏固知識。

**本身很容易理解,是利用 map 物件對資料進行快取,之後呼叫從 map 物件來取資料。對於及其簡單的業務場景,直接利用此**即可。

呼叫方式:

getwares().then( ... )

// 第二次呼叫 取得先前的data

getwares().then( ... )

方案一本身是不足的。因為如果考慮同時兩個以上的呼叫此 api,會因為請求未返回而進行第二次請求api。當然,如果你在系統中新增類似於 vuex、redux這樣的單一資料來源框架,這樣的問題不太會遇到,但是有時候我們想在各個複雜元件分別呼叫api,而不想對元件進行元件通訊資料時候,便會遇到此場景。

const promisecache = new map()

getwares() ).catch(error => )

}// 返回promise

return promise

}

該**避免了方案一的同一時間多次請求的問題。同時也在後端出錯的情況下對promise進行了刪除,不會出現快取了錯誤的promise就一直出錯的問題。

呼叫方式:

getwares().then( ... )

// 第二次呼叫 取得先前的promise

getwares().then( ... )

該方案是同時需要 乙個以上 的api請求的情況下,對資料同時返回,如果某乙個api發生錯誤的情況下。均不返回正確資料。

const querys =

const promisecache = new map()

async queryall(queryapiname) else ).catch(error => )

promisecache.set(api, promise)

promisecache.push(promise)}})

return promise.all(promiseapi).then(res => )

}

該方案是同時獲取多個伺服器資料的方式。可以同時獲得多個資料進行操作,不會因為單個資料出現問題而發生錯誤。

呼叫方式

queryall('wares').then( ... )

// 第二次呼叫 不會去取 wares,只會去skus

queryall(['wares', 'skus']).then( ... )

往往快取是有危害的,如果我們在知道修改了資料的情況下,直接把 cache 刪除即可,此時我們呼叫方法就可以向伺服器進行請求。這樣我們規避了前端顯示舊的的資料。但是我們可能一段時間沒有對資料進行操作,那麼此時舊的資料就一直存在,那麼我們最好規定個時間來去除資料。

該方案是採用了 類 持久化資料來做資料快取,同時新增了過期時長資料以及引數化。

**如下: 首先定義持久化類,該類可以儲存 promise 或者 data

class itemcache() 

}

然後我們定義該資料快取。我們採用map 基本相同的api

class expriescache 

// 不超時

return false

}// 當前data在 cache 中是否超時

static has(name)

// 刪除 cache 中的 data

static delete(name)

// 獲取

static get(name)

// 預設儲存20分鐘

static set(name, data, timeout = 1200)

}

此時資料類以及操作類 都已經定義好,我們可以在api層這樣定義

// 生成key值錯誤

const generatekeyerror = new error("can't generate key from name and argument")

// 生成key值

function generatekey(name, argument) :$`

}catch(_)

}async getware(params1, params2) )

// 使用 10s 快取,10s之後再次get就會 獲取null 而從服務端繼續請求

expriescache.set(key, res, 10)

}return data

}

該方案使用了 過期時間 和 api 引數不同而進行 快取的方式。已經可以滿足絕大部分的業務場景。

呼叫方式

getwares(1,2).then( ... )

// 第二次呼叫 取得先前的promise

getwares(1,2).then( ... )

// 不同的引數,不取先前promise

getwares(1,3).then( ... )

和方案四是的解法一致的,但是是基於修飾器來做。 **如下:

// 生成key值錯誤

const generatekeyerror = new error("can't generate key from name and argument")

// 生成key值

function generatekey(name, argument) :$`

}catch(_)

}function decorate(handledescription, entryargs) else

}}function handleapicache(target, name, descriptor, ...config)

let promise = expriescache.get(key)

if (!promise) )

// 使用 10s 快取,10s之後再次get就會 獲取null 而從服務端繼續請求

expriescache.set(key, promise, config[0])

}return promise

}return descriptor;

}// 制定 修飾器

function apicache(...args)

此時 我們就會使用 類來對api進行快取

class api 

}

因為函式存在函式提公升,所以沒有辦法利用函式來做 修飾器

例如:

var counter = 0;

var add = function () ;

@add

function foo()

該**意圖是執行後counter等於 1,但是實際上結果是counter等於 0。因為函式提公升,使得實際執行的**是下面這樣

@add

function foo()

var counter;

var add;

counter = 0;

add = function () ;

所以沒有 辦法在函式上用修飾器。具體參考ecmascript 6 入門 decorator

此方式寫法簡單且對業務層沒有太多影響。但是不可以動態修改 快取時間

呼叫方式

getwares(1,2).then( ... )

// 第二次呼叫 取得先前的promise

getwares(1,2).then( ... )

// 不同的引數,不取先前promise

getwares(1,3).then( ... )

api的快取機制與場景在這裡也基本上介紹了,基本上能夠完成絕大多數的資料業務快取,在這裡我也想請教教大家,有沒有什麼更好的解決方案,或者這篇部落格中有什麼不對的地方,歡迎指正,在這裡感謝各位了。

同時這裡也有很多沒有做完的工作,可能會在後面的部落格中繼續完善。

前端跨域請求及解決方案

跨域請求是當前發起請求的域 協議 網域名稱 埠 與該請求指向的資源所在的域不一致,常見的解決方式有 jsonp 跨域資源共享cors 反向 等 1 jsonp 2 跨域資源共享cors cross origin resource sharing 3 反向 最常用 在前端開發編碼過程中,常見的html...

前端開發API 豆瓣開放API

目錄前言 具體api 1 豆瓣熱映 2 電影top250 3 電影條目檢索 4 條目詳情 前後端的分離,在和後端對接之前,前端開發人員除錯的時候,總是面對沒有真實資料的尷尬地位。雖然有mock.js可以模擬資料,但是始終只是在本地進行模擬。而豆瓣提供的這些公開的介面,相信可以滿足大部分前端的開發。遺...

前端跨域請求get 解決前端跨域問題方案彙總

1.同源策略如下 url說明 是否允許通訊 同一網域名稱下 允許同一網域名稱下不同資料夾 允許同一網域名稱,不同埠 不允許同一網域名稱,不同協議 不允許網域名稱和網域名稱對應ip 不允許主域相同,子域不同 不允許同一網域名稱,不同二級網域名稱 同上 不允許 cookie這種情況下也不允許訪問 不同網...