使用 localStorage 的最佳實踐

2021-10-08 21:51:04 字數 4041 閱讀 4017

localstorage 是 html5 規範中作為持久化儲存客戶端資料的方案,localstorage 可以用於資料快取,日誌儲存等應用場景。由於 localstorage 本身的一些特性:

使用好 localstorage 並沒有那麼簡單,本文主要介紹其使用的一些最佳實踐。

由於瀏覽器對於新特性支援的速度和使用者瀏覽器的版本不同,在使用 localstorage 之前,需要先通過嗅探操作判斷當前環境是否支援:

function islocalstorageusable() 

localstorage.removeitem(localstoragetestkey);

return issupport;

} catch(e) 

}

讀寫操作雖然可以用來驗證當前瀏覽器是否支援 localstorage 特性,但是並非支援 localstorage 的瀏覽器一定可以進行寫操作,前面已經提到「瀏覽器給 localstorage 分配的儲存空間是有限的」,當儲存的內容已經到達上限,則無法再進行寫操作。

try 

localstorage.removeitem(localstoragetestkey);

return issupport;

} catch(e)  else 

return issupport;

}

// 類的例項方法

ready() 

if (this.issupport) 

return promise.reject();

}

通過定義上述的 ready 方法,使得嗅探方法具備「惰性執行」的特性。

當將物件直接作為鍵值對傳入 localstorage 時,會隱式呼叫 tostring 方法:

// 最終儲存的鍵值為 key:[object object] value: [object object]

localstorage.setitem({}, {});

如果不注意鍵名的型別,可能會出現因鍵名重複而造成資料丟失的問題。

當 localstorage 的 key 為物件時,應該給予適當的警告提示,一定程度上避免低階錯誤導致的 bug:

function normalizekey(key)  used as a key, but it is not a string.`);

key = string(key);

}return key;

}

對於 value,如果這樣處理,則使得儲存的值沒有什麼意義,所以需要根據資料的型別進行序列化和反序列化處理。

當呼叫 setitem 方法向 localstorage 中儲存值時,需要對儲存的值進行統一的序列化處理:

// 類的例項方法

setitem(key, value) 

serialize(value, (error, valuestring) => 

try  catch(e) 

})})

}

一般情況下,儲存的都是 json 格式的資料,利用 json.stringify 進行序列化處理:

function serialize(value, callback)  catch(e) 

}

這裡需要對 json.stringify 方法進行異常捕獲,「當序列化的物件存在迴圈引用時,該方法會丟擲異常」。反序列化處理時,同樣需要對 json.parse 進行異常捕獲,比較常見的錯誤:

json.parse('undefined');

// vm20179:1 uncaught syntaxerror: unexpected token u in json at position 0

針對這種情況,可以在 setitem 方法中做一層過濾處理:

if (value === undefined)
但是也不能完全避免掉非法的 json 字串,所以仍需要利用 try/catch 捕獲異常。

如果業務需求比較複雜,那麼需要通過判斷儲存值的具體型別來進行特定的序列化處理:

const tostring = object.prototype.tostring;

function serialize(value, callback) 

filereader.readasarraybuffer(value);

break;

default:

try  catch(e) }}

這裡增加了 blob 型別的儲存需求,需要利用 filereader + arraybuffer 將其序列化,另外需要識別符號來告訴反序列化過程中該值的型別。

json.stringify 方法在執行的過程中(執行時)需要分析物件的結構以及鍵值對的型別,這在處理複雜巢狀物件時是非常耗時的。

優化的手段實際上就是將這部分耗時的工作提到編譯階段,舉個例子:

const testobj = 

function stringify() ","lastname":"$","age":$}"`

}

const benchmark = require('benchmark');

const fastjson = require('fast-json-stringify');

const suite = new benchmark.suite();

const testobj = 

function stringify() ","lastname":"$","age":$}"`

}  suite.add('json.stringify obj', function () )

suite.add('fast-json-stringify obj', function () )

suite.on('cycle', (e) => console.log(e.target.tostring()))

.on('complete', function() `);

})suite.run()

得到的測試結果表明:無論是每秒執行測試**的次數還是相對最快速度的統計誤差,優化方案表現得更好。

# 測試結果

json.stringify obj x 1,695,618 ops/sec ±0.62% (90 runs sampled)

fast-json-stringify obj x 787,253,287 ops/sec ±0.36% (92 runs sampled)

fastest is fast-json-stringify obj

上述例子不具備通用性,在實際的業務開發中,可以利用自定義 json schema 來生成特定的 stringify 方法,有成熟的開源框架供選擇:

localstorage 是受同源策略限制的,這種隔離級別相當於是應用級別的,但是在實際的業務開發過程中,這種隔離級別部分場景是覆蓋不到的。

向 localstorage 中儲存鍵值對時,主要有以下特點:

如果當前應用中各個模組都有採用 localstorage 儲存資料的需求,那麼怎麼從模組級別去隔離呢?

因為鍵值對都是通過鍵名來索引,所以可以為鍵名加上命名空間來區分:

const keyprefix = name + '/'; 

localstorage.setitem(keyprefix + key, value);

在多儲存模組的情況下,直接呼叫 clear 方法會出現誤刪其它儲存模組資料的問題,引入命名空間之後,可以避免這樣的情況:

function clear(keyprefix) })}

你點的每個贊,我都認真當成了喜歡

localstorage原理與使用

首先自然是檢測瀏覽器是否支援本地儲存。在html5中,本地儲存是乙個window的屬性,包括localstorage和sessionstorage,從名字應該可以很清楚的辨認二者的區別,前者是一直存在本地的,後者只是伴隨著session,視窗一旦關閉就沒了。二者用法完全相同,這裡以localstor...

本地快取localstorage使用

最近做專案遇到乙個問題,即從 個人中心 點選進入 修改支付寶 需要自動獲取使用者手機號怎麼做?修改支付寶的api不提供使用者手機號資料,但是發現個人中心提供,於是想通過localstorage在個人中心頁面獲取到手機號然後儲存在本地快取,進入修改支付寶頁面後再獲取出來。經簡單查詢用法和實驗,如下 v...

資料儲存localStorage的使用方法

初始化資料庫。如果路徑為空,它將建立乙個記憶體資料庫 void localstorageinit const char fullpath 釋放分配的資源 void localstoragefree 設定儲存內容 void localstoragesetitem const char key,cons...