小程式中快取的正確使用
阿新 • • 發佈:2022-05-13
小程式提供了諸多的介面用於儲存本地快取資料,有點類似 localstorage 的使用。現在利用快取實現一個搜尋記錄的功能。
功能不復雜,但有幾個點需要考慮:
1、快取有上限,只儲存最近搜尋的20條記錄,多出沒有必要,且頁面顯示不全;
2、需要保證資料的唯一性;若搜尋內容相同,後面的搜尋內容應該覆蓋前面的記錄;
3、提供增刪查的介面。
於是封裝之後的實現如下:
class Record { constructor() { this.limitSize = 20; this.tag = 'word' } wordExist(word) { let all= this.getAllRecord(); if(!all.length) return false; let element = all.find(item => item.word === word); return element ? element.key : false; } // 歷史記錄快取, 使用同步介面 setRecord(word = '') { try { // 重複的記錄保證順序,先刪除之前的,再插入最新的。 let key = this.wordExist(word); if(key) { this.removeRecordByKey(key); } wx.setStorage({ key: this.tag + Date.now(), data: word }) } catch (error) { console.log(error) } } getWordByKey(key= '') { try { let word = wx.getStorageSync(key); return word; } catch (error) { console.log(error); } } getAllRecord() { try { const res = wx.getStorageInfoSync(); res.keys = res.keys.length ? res.keys.filter( i => i.includes(this.tag)) : []; if(!res.keys.length) return []; return res.keys.map(item => { return { key: item, word: this.getWordByKey(item) } }) } catch (e) { console.log(e); } } removeRecordByKey(key) { try { wx.removeStorageSync(key); } catch (error) { console.log(error) } } // 刪除所有歷史記錄 clearAllReacord() { try { let record = this.getAllRecord(); if(record.length) { record.forEach(item => { wx.removeStorageSync(item.key) }) } } catch (error) { console.log(error); } } } export default Record;
為什麼會這樣亂,是因為介面使用的諸多不便:
1、微信沒有返回全部資料的介面,只有獲取所有資料 key 的介面 getStorageInfoSync,想要獲取所有的鍵值對,只能先獲取key的集合,再遍歷 key獲取 value。
2、由於資料相同的key 會覆蓋掉原來該 key 對應的內容,所以要保證key的唯一性,又由於本地儲存的還有其他頁面的資料,這裡使用字串 'word' + 時間戳保證資料的唯一性和資料頁面的從屬關係。
3、插入資料之前,先要判斷是否已經存在和是否已經超限。可以看到為了實現邏輯,基本呼叫了所有資料快取的介面,所以插入資料是一個非常耗費效能的操作。
思考:
1、程式碼亂是介面不滿足要求,需要變通去實現對應的功能。如果直接有get方法返回所有資料,或者自動覆蓋前面的資料,可以降低複雜程度;
2、仔細思考功能,資料唯一、容量限制、自動覆蓋,實際上這是一個“佇列”,結合上述可以實現這樣一個特殊的佇列,既可以規避頻繁的讀寫本地資料,又可以簡化邏輯。只需要在頁面解除安裝的時候,將所有資料打包寫入快取即可。
class Queue { constructor() { this.limit = 20; let words = wx.getStorageSync('words'); if (words) { this.words = JSON.parse(words); // 取出快取資料 } else { this.words = []; } } getAll() { return this.words; } clearAll() { this.words = []; } get(index) { return this.words[index]; } remove(index) { return this.words.splice(index, 1); } set(element) { // 判斷是否超容 let length = this.words.length; if (length > this.limit) { this.words.shift(); } // 判斷是否重複 let index = this.words.indexOf(element); if (index !== -1) { this.words.splice(index, 1); //保證順序 } this.words.push(element); } stringify() { try { wx.setStorageSync('key', JSON.stringify(this.words)); } catch (e) { console.log(e); } } } export default Queue;
使用 Array 作為內部資料維護,相關的方法一應俱全,實現簡單。