1. 程式人生 > 其它 >小程式中快取的正確使用

小程式中快取的正確使用

小程式提供了諸多的介面用於儲存本地快取資料,有點類似 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 作為內部資料維護,相關的方法一應俱全,實現簡單。