Failed to execute 'setItem' on '**': Setting the value of '**' exceeded

複製該博主的博文
/****** 害怕博主怕博文刪除,所以複製了博主的文章做一個學習記錄

JavaScript 學習筆記 - LocalStorage
前言
本文主要介紹本地存儲的基本使用,以及它和 Cookie、SessionStorage 的區別。

簡單回顧 Cookie
在 HTML5 之前,本地存儲數據一般是通過 Cookie 來完成的。我們可以把 Cookie 理解爲一個長度有限的字符串,服務端和客戶端都能讀寫這個字符串,並且每次請求時,都會把 Cookie 發送到服務端。

通常,我們可以利用這個字符串來保存用戶名、密碼等數據,來實現記住密碼、自動登錄等功能。

但是,Cookie 本來就不是用來存儲數據的,所以會有一些侷限性:

存儲空間有限,最多也就是幾十 K 的大小。
每次請求都發送到服務器,浪費寬帶。
使用起來比較麻煩的,需要自己封裝操作函數。
本地存儲的簡單使用
本地存儲(LocalStorage)是一種基於鍵值對的持久化存儲方案。“持久化存儲”就意味着,如果不手動清除,數據就永遠不會過期。

基於鍵值對的存儲方案,使用起來是很方便的。我們可以通過 localStorage.setItem(key, value) 來保存數據。

比如保存一個用戶名:

javascript-demo/localstorage.html:

localStorage.setItem(‘name’, ‘hello’)
然後就可以通過 localStorage.getItem(key) 的方式來獲取數據:

localStorage.getItem(‘name’) // hello
LocalStorage 還支持直接對 localStorage 對象的屬性進行操作來存取數據,效果和 setItem、getItem 是一樣的。

localStorage.hi = ‘Hi’
console.log(localStorage.hi) // Hi
以上代碼等同於:

localStorage.setItem(‘hi’, ‘Hi’)
console.log(localStorage.getItem(‘hi’)) // Hi
存儲對象
本地存儲只支持字符串存儲,存儲任何類型的數據,都會被轉換成字符串。

javascript-demo/localstorage-number.html:

localStorage.setItem(‘age’, 1024)
console.log(typeof localStorage.getItem(‘age’)) // string
讀取完數據後,還要把數據轉成 Number 類型,很麻煩。有時候,我們還需要存儲複雜的數據結構。不可能像下面那樣將對象的屬性一個個存儲,再一個個讀取。

javascript-demo/localstorage-object.html:

// 保存對象
let obj = {
name: ‘hello’,
age: 1024
}
localStorage.setItem(‘name’, obj.name)
localStorage.setItem(‘age’, obj.age)
// 讀取對象
let newObj = {
name: localStorage.getItem(‘name’),
age: parseInt(localStorage.getItem(‘age’))
}
console.log(newObj)
這時,我們需要利用 JSON API,來簡單封裝本地存儲。原理是保存數據前,通過 JSON.stringify 把數據轉換成 JSON 字符串再保存;讀取數據後,通過 JSON.parse 把 JSON 字符串轉換成原來的值。

// 簡單封裝
const storage = {
set: function (key, value) {
localStorage.setItem(key, JSON.stringify(value))
},
get: function (key) {
return JSON.parse(localStorage.getItem(key))
}
}
// 保存對象
let obj = {
name: ‘hello’,
age: 1024
}
storage.set(‘obj’, obj)
// 讀取對象
console.log(storage.get(‘obj’))
這很方便,存取數字類型時也不需要轉換了。

storage.set(‘age’, 1024)
console.log(typeof storage.get(‘age’)) // number
API 介紹
一般來說,setItem 和 getItem 就足夠用了。這裏大致介紹一下常用的屬性和方法,有興趣的瞭解一下。

localStorage.length:獲得存儲的鍵值對的的個數。
localStorage.key(n):獲得存儲的第 n 個元素對的鍵值(也叫做鍵名,不要和值搞混了)(下標從 0 開始)。
localStorage.getItem(key):獲取 key 對應的 value。
localStorage.key:獲取 key 對應的 value,相當於 getItem。也可以直接賦值,則相當於 setItem。
localStorage.setItem(key, value):添加鍵值對到存儲。
localStorage.removeItem(key):移除鍵值爲 key 的鍵值對。
localStorage.clear():清除所有數據。
LocalStorage VS Cookie
在數據存儲方面,Cookie 的不足,也就是本地存儲的優勢,相對於 Cookie,本地存儲的優勢在於:

較大的存儲空間。雖然 W3C 對存儲空間沒有限制,但瀏覽器有。不同的瀏覽器的限制大小可能不同。IE8 上是 10MB,Chrome 是 5MB(數據源於網絡,本人未去證實)。在未來可能會更大。
不用每次請求都發送到服務器,提高請求速度。
足夠好用的 API 支持,操作簡單。
儘管本地存儲功能強大,但它和 Cookie 的分工不同,還無法用來取代 Cookie。

一般來說,Cookie 用來與服務器進行交互,而不是用來存儲。而 LocalStorage 僅用來存儲。

同源限制
LocalStorage 同樣受限於同源策略。不同源之間的數據無法共享。關於同源策略,不懂的可以看我的這篇文章:前端學習筆記 - 跨域

Session Storage
SessionStorage 和 LocalStorage 功能類似,區別僅僅是數據保存時間的不同而已。LocalStorage 是持久存儲的,如果不手動清除,數據就永遠不會失效。而 SessionStorage 的數據存儲在窗口對象中,一旦窗口對象沒了(用戶關閉瀏覽器或標籤頁),數據就會丟失。

我們可以簡單地測試一下:

javascript-demo/sessionstorage.html:

console.log(sessionStorage.getItem(‘name’))
sessionStorage.setItem(‘name’, ‘hello’)
console.log(sessionStorage.getItem(‘name’))
第一次運行時,控制檯輸出:

null
hello
刷新一下瀏覽器,控制檯輸出:

hello
hello
然後打開一個新標籤頁(不要關閉原來的標籤頁),在新標籤頁中打開示例,可以看到控制檯輸出:

null
hello
可見,對於不同的標籤頁,SessionStorage 是無法共享數據的。一旦關閉了標籤頁或瀏覽器,存儲的數據就再也找不回了。

應用
比如文章編輯器的實時保存(以及斷網時的保存策略)。
一些不重要的用戶設置。比如某些閱讀類的網站,用戶可以設置文章的字體大小、配色等。這些數據有時沒必要保存在數據庫。
比如。。。你仔細想想,還是有很多的。
需要注意的是,不要太依賴於本地存儲。本地存儲雖然是永久的,但隨時可能被用戶或瀏覽器清理掉。此外,不同瀏覽器間也是無法共享數據的。

總結

無聊的補充
我們可以這樣獲取已經佔用的存儲空間大小:

var total = unescape(encodeURIComponent(JSON.stringify(localStorage))).length;
console.log(total / 1024 + ‘K’)
5M 左右的空間,也是會用滿的:

for (let i = 0; i < 1024 * 1024; i++) {
localStorage.setItem(‘test’ + i, ‘hello’)
}
控制檯輸出:

Uncaught DOMException: Failed to execute ‘setItem’ on ‘Storage’: Setting the value of ‘test356613’ exceeded the quota.
意思是超出配額了。

我們也可以來測試你的瀏覽器對本地存儲的最大允許容量。

for (let i = 0; i < 1024 * 1024; i++) {
var total = unescape(encodeURIComponent(JSON.stringify(localStorage))).length;
console.log(total / 1024 / 1024 + ‘M’)

localStorage.setItem('test' + i, '0')

}
我試了兩個瀏覽器,360瀏覽器崩潰了,谷歌瀏覽器顯示 7M 多。

//////////////////

自己的問題:緩存的數據加載太多字段導致超過其內存,所以減少字段能讓加載數量變多

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章