在開發 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這種情況下也不允許訪問 不同網...