🧑💻 寫在開頭
點贊 + 收藏 === 學會🤣🤣🤣
首先明確一點,localStorage是同步的
🥝 一、首先為什麼會有這樣的問題
localStorage
是 Web Storage API 的一部分,它提供了一種儲存鍵值對的機制。localStorage
的資料是持久儲存在使用者的硬碟上的,而不是記憶體。這意味著即使使用者關閉瀏覽器或電腦,localStorage
中的資料也不會丟失,除非主動清除瀏覽器快取或者使用程式碼刪除。
當你透過 JavaScript 訪問 localStorage
時,瀏覽器會從硬碟中讀取資料或向硬碟寫入資料。然而,在讀寫操作期間,資料可能會被暫時存放在記憶體中,以提高處理速度。但主要的特點是它的永續性,以及它不依賴於會話的持續性。
🍉 二、硬碟不是io裝置嗎?io讀取不都是非同步的嗎?
是的,硬碟確實是一個 IO 裝置,而大部分與硬碟相關的作業系統級IO操作確實是非同步進行的,以避免阻塞程序。不過,在 Web 瀏覽器環境中,localStorage
的API是設計為同步的,即使底層的硬碟讀寫操作有著IO的特性。
js程式碼在訪問 localStorage
時,瀏覽器提供的API介面通常會處於js執行執行緒上下文中直接呼叫。這意味著儘管硬碟是IO裝置,當一個js執行流程訪問 localStorage
時,它將同步地等待資料讀取或寫入完成,該過程中js執行執行緒會阻塞。
這種同步API設計意味著開發者在操作 localStorage
時不需要考慮回撥函式或者Promise等非同步處理模式,可以按照同步程式碼的方式來編寫。不過,這也意味著如果涉及較多資料的讀寫操作時,可能對效能產生負面影響,特別是在主執行緒上,因為它會阻塞UI的更新和其他js的執行。
🍑 三、完整操作流程
localStorage
實現同步儲存的方式就是阻塞 JavaScript 的執行,直到資料的讀取或者寫入操作完成。這種同步操作的實現可以簡單概述如下:
- js執行緒呼叫: 當 JavaScript 程式碼執行一個
localStorage
的操作,比如localStorage.getItem('key')
或localStorage.setItem('key', 'value')
,這個呼叫發生在 js 的單個執行緒上。 - 瀏覽器引擎處理: 瀏覽器的 js 引擎接收到呼叫請求後,會向瀏覽器的儲存子系統發出同步IO請求。此時 js 引擎等待IO操作的完成。
- 檔案系統的同步IO: 瀏覽器儲存子系統對硬碟執行實際的儲存或檢索操作。儘管作業系統層面可能對檔案訪問進行快取或最佳化,但從瀏覽器的角度看,它會進行一個同步的檔案系統操作,直到這個操作返回結果。
- 操作完成返回: 一旦IO操作完成,資料要麼被寫入硬碟,要麼被從硬碟讀取出來,瀏覽器儲存子系統會將結果返回給 js 引擎。
- JavaScript執行緒繼續執行: js 引擎在接收到操作完成的訊號後,才會繼續執行下一條 js 程式碼。
在同步的 localStorage
操作期間,由於 js 的單執行緒性質,整個執行緒會阻塞,即不會執行其他任何js程式碼,也不會進行任何渲染操作,直到 localStorage
呼叫返回。
🍒 四、localStorage限制容量都是因為同步會阻塞的原因嗎?
- 資源公平分享:同一使用者可能會訪問大量不同的網站,如果沒有限制,隨著時間的積累,每個網站可能會消耗大量的本地儲存資源。這樣會導致本地儲存空間被少數幾個站點佔用,影響到使用者訪問其他網頁的體驗。限制大小可以確保所有網站都有公平的儲存機會。
- 防止濫用:如果沒有儲存限制,網站可能會濫用
localStorage
,儲存大量資料在使用者的裝置上,這可能導致裝置儲存空間迅速耗盡,也可能侵犯使用者的隱私。 - 效能限制:如之前提到的,
localStorage
的操作是阻塞的。如果網站能夠儲存大量資料,就會加劇讀寫操作對頁面效能的影響。 - 儲存效率:
localStorage
儲存的是字串形式的資料,不是為儲存大量或結構化資料設計的。當嘗試儲存過多資料時,效率會降低。 - 歷史和相容性:5MB 的限制很早就已經被大多數瀏覽器實現,並被作為一個非正式的標準被採納。儘管現在有些瀏覽器支援更大的
localStorage
,但出於跨瀏覽器相容性的考慮,開發者通常會假設這個限制。 - 瀏覽器政策:瀏覽器廠商可能會依據自己的政策來設定限制,可能是出於提供使用者更一致體驗的角度,或者是出於管理使用者資料的方便。
🍐 五、那indexDB會造成濫用嗎?
雖然它們提供了更大的儲存空間和更豐富的功能,但確實潛在地也可能被濫用。但是與相比 localStorage
增加了一些特性用來降低被濫用的風險:
- 非同步操作:
IndexedDB
是一個非同步API,即使它被用來處理更大量的資料,也不會像localStorage
那樣阻塞主執行緒,從而避免了對頁面響應性的直接影響。 - 使用者提示和許可權:對於某些瀏覽器,當網站嘗試儲存大量資料時,瀏覽器可能會彈出提示,要求使用者授權。這意味著使用者有機會拒絕超出合理範圍的儲存請求。
- 儲存配額和限制:儘管
IndexedDB
提供的儲存容量比localStorage
大得多,但它也不是無限的。瀏覽器會為IndexedDB
設定一定的儲存配額,這個配額可能基於可用磁碟空間的一個百分比或者是一個事先設定的限額。配額超出時,瀏覽器會拒絕更多的儲存請求。 - 更清晰的儲存管理:
IndexedDB
的資料庫形式允許有組織的儲存和更容易的資料管理。使用者或開發者可以更容易地檢視和清理佔用的資料。 - 逐漸增加的儲存:某些瀏覽器實現
IndexedDB
儲存時,可能會在資料庫大小增長到一定閾值時,提示使用者是否允許繼續儲存,而不是一開始就分配一個很大的空間。
🤖 六、一個例子簡單測試一下
其實也不用測,平時寫的時候你也沒用非同步的方式寫localStorage吧,我們這裡簡單寫個例子
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> const testLocalStorage = () => { console.log("==========> 設定localStorage之前"); localStorage.setItem('testLocalStorage', '我是同步的'); console.log("==========> 獲取localStorage之前"); console.log('=========獲取localStorage', localStorage.getItem('testLocalStorage')) console.log("==========> 獲取localStorage之後"); } testLocalStorage() </script> </body> </html>
本文轉載於:https://juejin.cn/post/7359405716090011659
如果對您有所幫助,歡迎您點個關注,我會定時更新技術文件,大家一起討論學習,一起進步。