<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          前端最能打的本地存儲方案

          共 6348字,需瀏覽 13分鐘

           ·

          2024-04-11 08:59


          來源:網(wǎng)絡(luò)

          前言

          之前開發(fā)了一個離線存儲的需求,需要在本地存儲較大的數(shù)據(jù)量,并且還要考慮到多種場景下的存儲方式兼容。 產(chǎn)品的原話就是“要又大又全”。 既然存儲量大,也要覆蓋全多種設(shè)備多種瀏覽器。

          方案選擇

          • 既然要存儲的數(shù)量大,得排除cookie
          • localStorage,雖然比cookie多,但是同樣有上限(5M)左右,備選
          • websql 使用簡單,存儲量大,兼容性差,備選
          • indexDB api多且繁瑣,存儲量大、高版本瀏覽器兼容性較好,備選

          既然羅列了一些選擇,都沒有十全十美的,那么有沒有一種能夠集合這多種方式的插件呢?漸進(jìn)增強 or 優(yōu)雅降級 的存在
          沖著這個想法,就去github和谷歌找了一下,還真的有這么一個插件。
          那就是 localforage 

          localforage

          localForage 是一個 JavaScript 庫,只需要通過簡單類似 localStorage API 的異步存儲來改進(jìn)你的 Web 應(yīng)用程序的離線體驗。它能存儲多種類型的數(shù)據(jù),而不僅僅是字符串。

          關(guān)于兼容性

          localForage 有一個優(yōu)雅降級策略,若瀏覽器不支持 IndexedDB 或 WebSQL,則使用 localStorage。在所有主流瀏覽器中都可用:Chrome,F(xiàn)irefox,IE 和 Safari(包括 Safari Mobile)。下面是 indexDB、web sql、localStorage 的一個瀏覽器支持情況,可以發(fā)現(xiàn),兼容性方面loaclForage基本上滿足99%需求093e5fc48e4e6d16d8a32e49ee3d92ea.webp

          f106a8529f7e909f446deaafd46b3ee7.webp
          d5d5240fb16d22e71158d0cd141744a5.webp

          關(guān)于存儲量

          首先indexDB的存儲,理論上是硬件有多大內(nèi)存就可以存多少,但是有些瀏覽器廠商會限制,具體限制各家不同,但是基本最小是250M起步

          使用

          解決了兼容性和存儲量的點,我們就來看看localforage的基礎(chǔ)用法

          安裝

              # 通過 npm 安裝:
          npm install localforage

              // 直接引用
          <script src="localforage.js"></script>
          <script>console.log('localforage is: ', localforage);</script>

          獲取存儲

          getItem(key, successCallback)

          從倉庫中獲取 key 對應(yīng)的值并將結(jié)果提供給回調(diào)函數(shù)。如果 key 不存在,getItem() 將返回 null

              localforage.getItem('somekey').then(function(value) {
              // 當(dāng)離線倉庫中的值被載入時,此處代碼運行
              console.log(value);
          }).catch(function(err) {
              // 當(dāng)出錯時,此處代碼運行
              console.log(err);
          });

          // 回調(diào)版本:
          localforage.getItem('somekey'function(err, value) {
              // 當(dāng)離線倉庫中的值被載入時,此處代碼運行
              console.log(value);
          });

          設(shè)置存儲

          setItem(key, value, successCallback)

          將數(shù)據(jù)保存到離線倉庫。你可以存儲如下類型的 JavaScript 對象:

          • Array
          • ArrayBuffer
          • Blob
          • Float32Array
          • Float64Array
          • Int8Array
          • Int16Array
          • Int32Array
          • Number
          • Object
          • Uint8Array
          • Uint8ClampedArray
          • Uint16Array
          • Uint32Array
          • String
              localforage
            .setItem("somekey""some value")
            .then(function (value) {
              // 當(dāng)值被存儲后,可執(zhí)行其他操作
              console.log(value);
            })
            .catch(function (err) {
              // 當(dāng)出錯時,此處代碼運行
              console.log(err);
            });

          // 不同于 localStorage,你可以存儲非字符串類型
          localforage
            .setItem("my array", [1, 2, "three"])
            .then(function (value) {
              // 如下輸出 `1`
              console.log(value[0]);
            })
            .catch(function (err) {
              // 當(dāng)出錯時,此處代碼運行
              console.log(err);
            });

          // 你甚至可以存儲 AJAX 響應(yīng)返回的二進(jìn)制數(shù)據(jù)
          req = new XMLHttpRequest();
          req.open("GET""/photo.jpg"true);
          req.responseType = "arraybuffer";

          req.addEventListener("readystatechange"function () {
            if (req.readyState === 4) {
              // readyState 完成
              localforage
                .setItem("photo", req.response)
                .then(function (image) {
                  // 如下為一個合法的 <img> 標(biāo)簽的 blob URI
                  var blob = new Blob([image]);
                  var imageURI = window.URL.createObjectURL(blob);
                })
                .catch(function (err) {
                  // 當(dāng)出錯時,此處代碼運行
                  console.log(err);
                });
            }
          });

          刪除存儲

          removeItem(key, successCallback)

          從離線倉庫中刪除 key 對應(yīng)的值。

              localforage.removeItem('somekey').then(function() {
              // 當(dāng)值被移除后,此處代碼運行
              console.log('Key is cleared!');
          }).catch(function(err) {
              // 當(dāng)出錯時,此處代碼運行
              console.log(err);
          });

          清空存儲

          clear(successCallback)

          從數(shù)據(jù)庫中刪除所有的 key,重置數(shù)據(jù)庫。

          localforage.clear() 將會刪除離線倉庫中的所有值。謹(jǐn)慎使用此方法。

              localforage.clear().then(function() {
              // 當(dāng)數(shù)據(jù)庫被全部刪除后,此處代碼運行
              console.log('Database is now empty.');
          }).catch(function(err) {
              // 當(dāng)出錯時,此處代碼運行
              console.log(err);
          });

          更多

          除了基本的增刪查改,還有一些配置,如指定具體使用哪一種存儲方式、設(shè)置數(shù)據(jù)庫的名稱、長度等信息 可參考 官方文檔

          localforage是否萬事大吉?

          用上了localforage一開始我也以為可以完全滿足萬惡的產(chǎn)品了,然而。。。翻車了

          問題

          在這個功能上線半年,一直相安無事,有一天晚上突然產(chǎn)品說接到反饋說有用戶的手機(jī)進(jìn)入頁面沒有緩存上次的操作數(shù)據(jù)。
          我第一反應(yīng),“不可能,絕對不可能”

          707928abd0702b9a8c885baff537626c.webp我詢問了一下,用戶的手機(jī)是什么型號,當(dāng)我看到手機(jī)圖片的時候。。。我是沒想到。。。
          如下圖:

          b85f00ea0ab799753c4a02293f12bde8.webp

          這玩意,一些小年輕都可能沒見過。。。。iphone4哇,現(xiàn)在是出到了iphone14了吧???
          不得了不得了,iphone4居然也是我們的用戶群體???

          分析

          既然遇上了,還是冷靜分析一下吧。起初第一反應(yīng)是這古董機(jī)的兼容性有問題,是不是只支持localstorage導(dǎo)致只能存儲5M的內(nèi)容,超過了上限,導(dǎo)致無法緩存了?

          然而,當(dāng)產(chǎn)品不知道從哪找到了一部iphone4給我(我也真的服了這個老6),我拿到真機(jī)試了下,得到讓我無法呼吸的結(jié)果,iphone4這古董機(jī)居然支持indexDB,那么就不是超過了5M的上限導(dǎo)致緩存失敗了

          進(jìn)一步假設(shè)

          在知道iphone4居然支持indexDB后,我失去頭緒了,拿著十年前的這個古董機(jī),隨便翻翻,看看系統(tǒng),看看版本,沒看出什么問題,但是我發(fā)現(xiàn)這iphone4的內(nèi)存也是出奇的小,只有8G內(nèi)存。等等,8G內(nèi)存,如果手機(jī)內(nèi)存不足的前提下,localforage繼續(xù)緩存會怎么樣?
          隨即,隨便下載點軟件,毫不費力就將這臺iphone4的內(nèi)存整得只剩下50M不到了,手機(jī)已經(jīng)開始提示要清理內(nèi)存。
          在這種狀態(tài)下,嘗試使用localforage,不出意外,拋錯了 QuotaExceededError 的 DOMError

          延伸

          雖然現(xiàn)在的硬件設(shè)備內(nèi)存大部分都很大,但是本著產(chǎn)品的“又大又全”理念,還是打算處理一下。當(dāng)然除了處理這臺古董機(jī),也延伸出更多優(yōu)化的可能性

          • 當(dāng)設(shè)備不支持 indexDB和web sql的時候,只支持loaclStorage存儲量只有5M,應(yīng)該怎么處理?
          • 如果存儲數(shù)據(jù)出現(xiàn)了臟數(shù)據(jù)或者讀取問題,想要清理用戶設(shè)備上的數(shù)據(jù)怎么處理?

          解決

          存儲數(shù)據(jù)的時候加上存儲的時間戳和模塊標(biāo)識,加時間戳一起存儲

              setItem({
              value: '1',
              label: 'a',
              module: 'a',
              timestamp: '11111111111'
          })

          • 如果是遇到存儲使用報錯的情況,try/catch捕獲之后,通過判斷報錯提示,去執(zhí)行相應(yīng)的操作,遇到內(nèi)存不足的情況,則根據(jù)時間戳和模塊標(biāo)識清理一部分舊數(shù)據(jù)(內(nèi)存不足的情況還是比較少的)
          • 在用戶手機(jī)上產(chǎn)生臟數(shù)據(jù)的情況,想要清理的這種情況的 處理方式是:
          1. 讓后端在用戶信息接口里面加上緩存有效期時間戳,當(dāng)該時間戳存在,則前端會進(jìn)行一次對本地存儲掃描
          2. 在有效期時間戳之前的數(shù)據(jù),結(jié)合模塊標(biāo)識,進(jìn)行清理,清理完畢后調(diào)用后端接口上報清理日志
          3. 模塊標(biāo)識的意義是清理數(shù)據(jù)的時候,可以按照模塊去清理(選填)
          a02405963f60865a806eceb8eb1fc440.webp
          推薦閱讀  點擊標(biāo)題可跳轉(zhuǎn)

          1、JS 中變量存儲在堆中還是棧中?(深入內(nèi)存原理)

          2、Vue3+Pinia+Koa+Three.js 全棧電商項目總結(jié)復(fù)盤

          3、還在封裝 xxxForm,xxxTable 殘害你的同事?試試這個工具

          瀏覽 42
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  豆花视频在线 | 天堂va欧美ⅴa亚洲va一夜 | 人妻巨大乳一二三区 | 91爱福利| 国产精品久久久久久亚洲毛片 |