摘要:字節流這個簡單的模型將數據存儲為長度不透明的字節字符串變量,將任何形式的內部組織留給應用層。字節流數據存儲的代表例子包括文件系統和云存儲服務。使用同步存儲會阻塞主線程,并為應用程序的創建凍結體驗。
這是專門探索 JavaScript 及其所構建的組件的系列文章的第 16 篇。
想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你!
如果你錯過了前面的章節,可以在這里找到它們:
JavaScript 是如何工作的:引擎,運行時和調用堆棧的概述!
JavaScript 是如何工作的:深入V8引擎&編寫優化代碼的5個技巧!
JavaScript 是如何工作的:內存管理+如何處理4個常見的內存泄漏!
JavaScript 是如何工作的:事件循環和異步編程的崛起+ 5種使用 async/await 更好地編碼方式!
JavaScript 是如何工作的:深入探索 websocket 和HTTP/2與SSE +如何選擇正確的路徑!
JavaScript 是如何工作的:與 WebAssembly比較 及其使用場景!
JavaScript 是如何工作的:Web Workers的構建塊+ 5個使用他們的場景!
JavaScript 是如何工作的:Service Worker 的生命周期及使用場景!
JavaScript 是如何工作的:Web 推送通知的機制!
JavaScript是如何工作的:使用 MutationObserver 跟蹤 DOM 的變化!
JavaScript是如何工作的:渲染引擎和優化其性能的技巧!
JavaScript是如何工作的:深入網絡層 + 如何優化性能和安全!
JavaScript是如何工作的:CSS 和 JS 動畫底層原理及如何優化它們的性能!
JavaScript的如何工作的:解析、抽象語法樹(AST)+ 提升編譯速度5個技巧!
JavaScript是如何工作的:深入類和繼承內部原理+Babel和 TypeScript 之間轉換!
概述在設計 Web 應用程序時,為本地瀏覽器選擇合適的存儲機制至關重要, 一個好的存儲引擎可以確保可靠地保存信息,減少帶寬,提高響應能力。正確的存儲緩存策略是實現離線移動 Web 體驗的核心構建塊,同時也大大的提高了用戶體驗。
在本章中,討論可選擇的存儲 Api 和服務,并提供一些在構建 Web應用程序,該使用哪種存儲引擎。
數據模型數據存儲模型確定數據在內部的組織方式,這會影響 Web 應用程序的整個設計,合理的數據模式會讓 Web 應用程序在完成它應有的任務下還能讓運行速度更加高效。對于所有與工程相關的問題,沒有存在最好的解決方法,也沒有適用于所有問題的解決方案,不同場景下有不同的選擇。所以,來看看可選擇的數據模型:
結構化: 存儲在具有預定義字段的表中的數據(這是典型的基于 SQL 的數據庫管理系統)適行靈活的動態查詢。瀏覽器中結構化數據存儲的一個代表的例子是 IndexedDB。
Key/Value: 鍵/值 數據存儲和相關的 NoSQL 數據庫提供了存儲和檢索由唯一鍵索引的非結構化數據的能力。鍵/值 數據存儲類似于哈希表,因為它們允許對索引的不透明數據進行長時間訪問。 鍵/值 數據存儲的代表例子是瀏覽器中的 Cache API 和服務器上的 Apache Cassandra。
Apache Cassandra 是一套開源分布式數據庫管理系統,由Facebook開發,用于儲存特別大的數據。
字節流:這個簡單的模型將數據存儲為長度不透明的字節字符串變量,將任何形式的內部組織留給應用層。這個模型特別適合于文件系統和其他分層組織的數據塊。字節流數據存儲的代表例子包括文件系統和云存儲服務。
持久化web 應用程序的存儲方法可以根據數據持久化的時間段進行劃分:
會話持久化: 該類別中的數據僅在單個 Web 會話或瀏覽器選項卡保持激活狀態時才持久,具有會話持久性的存儲機制的一個示例是 Session Storage API。
設備的持久化: 此類別中的數據在特定設備上跨會話和瀏覽器選項卡/窗口持久化,具有設備持久化的存儲機制的一個示例是 Cache API。
此類中的數據跨會話和設備持久化。因此,它是最健壯的數據持久性形式。但是,它不能存儲在設備本身上,這意味需要在某種服務器端存儲。在這里不會詳細討論它,因為本文的重點是在設備本身上存儲數據。
瀏覽器中的數據持久化現在,有相當多的瀏覽器 Api 用來存儲數據。這里將逐一介紹其中的一些及它們的區別,以便后續我們能夠容合理的選擇使用。
然而,在選擇如何持久化數據之前,有幾件事需要考慮。當然,有必要知道的的第一件事是你的 Web 應用程序應用場景是什么,以及以后如何迭代和豐富。即使你知道了這些,最終也會有幾個選擇。所以,以下是需要了解的:
瀏覽器支持 ?—? 標準化和完善的 API 更值得我們選擇,因為它們往往壽命更長,支持更廣泛, 這些API 還享有更豐富的文檔和開發人員社區。
事務 —?有時,相關存儲操作的集合原子地成功或失敗是很重要的。傳統上,數據庫使用事務模型支持此功能,其中相關更新可以分組到任意單元中。
同步/異步 — 有些存儲 Api 是同步的,因為存儲或檢索請求會阻塞當前活動的線程,直到請求完成。使用同步存儲 API 會阻塞主線程,并為 Web 應用程序的 UI 創建凍結體驗。如果可能,使用異步API。
比較在本節中,了解決 Web 開發人員的當前可用存儲 Api,并從各個維度上進行比較。
文件系統API通過 FileSystem API, Web 應用就可以創建、讀取、導航用戶本地文件系統中的沙盒部分以及向其中寫入數據。
API 被分為以下不同的主題:
讀取和處理文件:File/Blob、FileList、FileReader
創建和寫入:BlobBuilder、FileWriter
目錄和文件系統訪問:DirectoryReader、FileEntry/DirectoryEntry、LocalFileSystem
FileSystem API 是非標準 API。在發布環境因慎重使用,因為并是所有的瀏覽器都支持,實現方式可能存在很大的不兼容性,并且在將來可能也會發生變化。
請求文件系統網絡應用可通過調用 window.requestFileSystem() 請求對沙盒文件系統的訪問權限:
// Note: The file system has been prefixed as of Google Chrome 12: window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; window.requestFileSystem(type, size, successCallback, opt_errorCallback)
type:文件存儲是否應該是持久的??赡艿闹蛋?window.TEMPORARY 和 window.PERSISTENT。通過 TEMPORARY 存儲的數據可由瀏覽器自行決定刪除(例如在需要更多空間的情況下),要清除PERSISTENT 存儲,必須獲得用戶或應用的明確授權,并且需要用戶向你的應用授予配額。
size: 應用需要用于存儲的大小 (以字節為單位)。
successCallback:文件系統請求成功時調用的回調,其參數為 FileSystem 對象。
opt_errorCallback: 用于處理錯誤或獲取文件系統的請求遭到拒絕時可選的回調,其參數為 FileError 對象。
如果你是首次調用 requestFileSystem(),系統會為你的應用創建新的存儲。請注意,這是沙箱文件系統,也就是說,一個網絡應用無法訪問另一個應用的文件。
在訪問文件系統之后,可以對文件和目錄執行大多數標準操作。
與其他存儲類型相比,文件系統是一個完全不同的存儲類型,因為它的旨在滿足數據庫,很不能很好地服務的客戶端存儲用例。通常,這些應用程序處理大型二進制blob或與瀏覽器上下文之外的應用程序共享數據。
以下使用文件系統 API 的幾個示例:
有上傳的應用
當你選擇一個文件或目錄進行上傳時,你可以賦值文件到一個本地沙盒并一次上傳一個塊。
應用可以在一次中斷后重新上傳,中斷可能包括瀏覽器被關閉或崩潰,連接中斷,或電腦被關閉。
視頻游戲或其他使用大量媒體資源的應用
用下載一個或多個大壓縮包并在本地將他們解壓到一個文件目錄中。
應用能在后臺預取資源,從而讓用戶能夠進入下一項工作或游戲等級,而不需要等待下載。
音頻或照片編輯器使用線下訪問或本地緩存
應用可以分段寫入文件(例如只覆蓋ID3/EXIF標簽而不是整個文件)。
線下視頻瀏覽
應用可以訪問只下載了部分的文件。
線下網絡郵件客戶端
客戶端下載附件并在本地存儲它們。
客戶端緩存附件用于稍后的上傳。
目前瀏覽器對文件系統 API 的支持:
Local storage只讀的 localStorage 允許你訪問一個 Document 的遠端(origin)對象 Storage;其存儲的數據能在跨瀏覽器會話保留。 localStorage 類似 sessionStorage,其區別在于:存儲在 localStorage 的數據可以長期保留;而當頁面會話結束——也就是說當頁面被關閉時,存儲在 sessionStorage 的數據會被清除 。
應注意無論數據存儲在 localStorage 還是 sessionStorage ,它們都特定于頁面的協議。
另外,localStorage 中的鍵值對總是以字符串的形式存儲。
當前瀏覽器對API的支持:
Session storagesessionStorage 屬性允許你訪問一個 session Storage 對象。它與 localStorage 相似,不同之處在于 localStorage 里面存儲的數據沒有過期時間設置,而存儲在 sessionStorage 里面的數據在頁面會話結束時會被清除。頁面會話在瀏覽器打開期間一直保持,并且重新加載或恢復頁面仍會保持原來的頁面會話。在新標簽或窗口打開一個頁面時會在頂級瀏覽上下文中初始化一個新的會話,這點和 session cookies 的運行方式不同。
應該注意的是,無論是 localStorage 還是 sessionStorage 中保存的數據都僅限于該頁面的協議。
當前瀏覽器對API的支持:
CookiesHTTP Cookie(也叫Web Cookie或瀏覽器Cookie)是服務器發送到用戶瀏覽器并保存在本地的一小塊數據,它會在瀏覽器下次向同一服務器再發起請求時被攜帶并發送到服務器上。通常,它用于告知服務端兩個請求是否來自同一瀏覽器,如保持用戶的登錄狀態。Cookie 使基于無狀態的 HTTP 協議記錄穩定的狀態信息成為了可能。
Cookie主要用于以下三個方面:
會話狀態管理(如用戶登錄狀態、購物車、游戲分數或其它需要記錄的信息)
個性化設置(如用戶自定義設置、主題等)
* 瀏覽器行為跟蹤(如跟蹤分析用戶行為等)
Cookie曾一度用于客戶端數據的存儲,因當時并沒有其它合適的存儲辦法而作為唯一的存儲手段,但現在隨著現代瀏覽器開始支持各種各樣的存儲方式,Cookie漸漸被淘汰。由于服務器指定Cookie后,瀏覽器的每次請求都會攜帶Cookie數據,會帶來額外的性能開銷(尤其是在移動環境下)。
cookie 類型有兩種:
會話 Cookie ?—? 瀏覽器關閉之后它會被自動刪除,也就是說它僅在會話期內有效。會話期Cookie不需要指定過期時間(Expires)或者有效期(Max-Age)。需要注意的是,有些瀏覽器提供了會話恢復功能,這種情況下即使關閉了瀏覽器,會話期Cookie也會被保留下來,就好像瀏覽器從來沒有關閉一樣。
持久 Cookie —?和關閉瀏覽器便失效的會話期Cookie不同,持久性Cookie可以指定一個特定的過期時間(Expires)或有效期(Max-Age)。
當機器處于不安全環境時,切記不能通過HTTP Cookie存儲、傳輸敏感信息,且所有瀏覽器都廣泛支持cookie。
CacheCache 接口為緩存的 Request/Response 對象對提供存儲機制,例如,作為 ServiceWorker 生命周期的一部分。請注意,Cache 接口像 workers 一樣,是暴露在 window 作用域下的。盡管它被定義在 service worker 的標準中, 但是它不必一定要配合 service worker 使用.
一個域可以有多個命名 Cache 對象。你需要在你的腳本 (例如,在 ServiceWorker 中)中處理緩存更新的方式。除非明確地更新緩存,否則緩存將不會被更新;除非刪除,否則緩存數據不會過期。使用 CacheStorage.open(cacheName) 打開一個Cache 對象,再使用 Cache 對象的方法去處理緩存.
你需要定期地清理緩存條目,因為每個瀏覽器都硬性限制了一個域下緩存數據的大小。緩存配額使用估算值,可以使用 StorageEstimate API 獲得。瀏覽器盡其所能去管理磁盤空間,但它有可能刪除一個域下的緩存數據。瀏覽器要么自動刪除特定域的全部緩存,要么全部保留。確保按名稱安裝版本緩存,并僅從可以安全操作的腳本版本中使用緩存。查看 Deleting old caches 獲取更多信息.
CacheStorage 接口表示 Cache 對象的存儲。
它提供了一個 ServiceWorker,其它類型worker或者 window 范圍內可以訪問到的所有命名cache的主目錄(它并不是一定要和 service workers 一起使用,即使它是在 service workers 規范中定義的),并維護一份字符串名稱到相應 Cache 對象的映射。
使用 CacheStorage.open() 獲取 Cache 實例。
使用 CacheStorage.match() 檢查給定的 Request 是否是 CacheStorage 對象跟蹤的任何 Cache 對象中的鍵。
你可以通過 caches 屬性訪問 CacheStorage .
IndexedDBIndexedDB 是一種在用戶瀏覽器中持久存儲數據的方法。因為它允許你創建具有豐富查詢功能的 Web 應用程序,無論網絡可用性如何,這些應用程序都可以在線和離線工作。IndexedDB 對于存儲大量數據的應用程序(例如,借出庫中的 DVD 目錄)和不需要持久 internet 連接才能工作的應用程序(例如,郵件客戶機、待辦事項列表和記事本)非常有用。
在本文中,會更詳細地討論存儲數據庫,因為其余的存儲 Api 都是眾所周知的。另外,隨著 Web 應用程序的復雜性越來越高,IndexedDB 也越來越受歡迎。
IndexedDB的內部結構IndexedDB 通過“鍵”來存儲和檢索對象。對數據庫所做的所有更改都發生在事務中,像大多數 Web 存儲解決方案一樣,IndexedDB 遵循同源策略。因此,雖然可以訪問域中存儲的數據,但是不能跨不同的域訪問數據。
IndexedDB 是一個 異步 API,可以在大多數上下文中使用,包括 WebWorkers。它過去也包括一個同步版本,供 Web 開發者使用,但是由于 Web 社區對它缺乏興趣,所以從規范中刪除了這個版本。
IndexedDB 曾經有一個與之競爭的規范,稱為 WebSQL 數據庫,但是 W3C 棄用了它。雖然 IndexedDB 和WebSQL 都是存儲解決方案,但它們提供的功能不同。WebSQL 數據庫是一個關系數據庫訪問系統,而IndexedDB 是一個索引表系統。
不要一開始就使用 IndexedDB,這依賴于你對其他類型數據庫的假設。相反,應該仔細閱讀文檔,以下是一些需要牢記的基本概念:
IndexedDB 數據庫使用 key-value 鍵值對儲存數據 ?—? values 數據可以是結構非常復雜的對象,key可以是對象自身的屬性。你可以對對象的某個屬性創建索引(index)以實現快速查詢和列舉排序。key可以是二進制對象。
IndexedDB 是事務模式的數據庫 —? 任何操作都發生在事務(transaction)中。 IndexedDB API提供了索引(indexes)、表(tables)、指針(cursors)等等,但是所有這些必須是依賴于某種事務的。因此,你不能在事務外執行命令或者打開指針。事務(transaction)有生存周期,在生存周期以后使用它會報錯。并且,事務(transaction)是自動提交的,不可以手動提交。
The IndexedDB API 基本上是異步的 — IndexedDB 的 API 不通過 return 語句返回數據,而是需要你提供一個回調函數來接受數據。執行 API 時,你不以同步(synchronous)方式對數據庫進行“存儲”和“讀取”操作,而是向數據庫發送一個操作“請求”。當操作完成時,數據庫會以DOM事件的方式通知你,同時事件的類型會告訴你這個操作是否成功完成。這個過程聽起來會有些復雜,但是里面是有明智的原因的。這個和 XMLHttpRequest 請求是類似的。
IndexedDB數據庫“請求”無處不在 — 每一個“請求”都包含 onsuccess 和 onerror 事件屬性,同時你還對 “事件” 調用 addEventListener() 和 removeEventListener()?!罢埱蟆?還包括 readyState,result 和 errorCode 屬性,用來表示“請求”的狀態。result 屬性尤其神奇,他可以根據“請求”生成的方式變成不同的東西,例如:IDBCursor 實例、剛插入數據庫的數值對應的鍵值(key)等。
IndexedDB是面向對象的 — indexedDB 不是用二維表來表示集合的關系型數據庫,這一點非常重要,將影響你設計和建立你的應用程序。
indexedDB 不使用結構化查詢語言(SQL) — 它通過索引(index)所產生的指針(cursor)來完成查詢操作,從而使你可以迭代遍歷到結果集合。如果你不熟悉NoSQL系統,可以參考維基百科相關文章。
IndexedDB遵循同源(same-origin)策略 — “源”指腳本所在文檔URL的域名、應用層協議和端口。每一個“源”都有與其相關聯的數據庫。在同一個“源”內的所有數據庫都有唯一、可區別的名稱。
IndexedDB局限性以下情況不適合使用IndexedDB
全球多種語言混合存儲。國際化支持不好。需要自己處理。
和服務器端數據庫同步。你得自己寫同步代碼。
全文搜索。IndexedDB 接口沒有類似 SQL 語句中 LIKE 的功能。
注意,在以下情況下,數據庫可能被清除:
用戶請求清除數據。
瀏覽器處于隱私模式。最后退出瀏覽器的時候,數據會被清除。
硬盤等存儲設備的容量到限。
數據損壞。
進行與特性不兼容的操作。
確切的環境和瀏覽器特性會隨著時間改變,但瀏覽器廠商通常會遵循盡最大努力保留數據的理念。
確切的環境和瀏覽器特性會隨著時間改變,但瀏覽器廠商通常會遵循盡最大努力保留數據的理念。
選擇正確的存儲API如前所述,最好選擇盡可能多的瀏覽器廣泛支持的 Api,并提供異步調用模型,以最大限度地提高 UI 響應能力。這些標準自然會導致以下技術選擇:
對于離線存儲,請使用 Cache API。任何支持創建離線應用程序所需的 Service Worker technology 的瀏覽器都可以使用這個 API,Cache API 非常適合存儲與已知 URL 關聯的資源。
要存儲應用程序狀態和用戶生成的內容,請使用IndexedDB。這使得用戶可以在更多的瀏覽器中離線工作,而不僅僅是那些支持緩存API的瀏覽器。
原文:
https://blog.sessionstack.com...
這篇主要一些內容原作者大部分是通過 MDN 整理的組合的,我也是根據中文的 MND 整理的組合。
你的點贊是我持續分享好東西的動力,歡迎點贊!
歡迎加入前端大家庭,里面會經常分享一些技術資源。文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101431.html
摘要:為了方便大家共同學習,整理了之前博客系列的文章,目前已整理是如何工作這個系列,可以請猛戳博客查看。以下列出該系列目錄,歡迎點個星星,我將更友動力整理理優質的文章,一起學習。 為了方便大家共同學習,整理了之前博客系列的文章,目前已整理 JavaScript 是如何工作這個系列,可以請猛戳GitHub博客查看。 以下列出該系列目錄,歡迎點個星星,我將更友動力整理理優質的文章,一起學習。 J...
摘要:調用堆棧是存放原始數據類型的地方除了函數調用之外。上一節中聲明變量后調用堆棧的粗略表示如下。解釋改變的正確方法是更改內存地址。在聲明時,將在調用堆棧上分配內存地址,該值是在堆上分配的內存地址。 這是專門探索 JavaScript 及其所構建的組件的系列文章的第 21 篇。 想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你! 如果你錯過了前面的章節,可以在這里找到它們:...
摘要:與大多數全局對象不同,沒有構造函數。為什么要設計更加有用的返回值早期寫法寫法函數式操作早期寫法寫法可變參數形式的構造函數一般寫法寫法當然還有很多,大家可以自行到上查看什么是代理設計模式代理模式,為其他對象提供一種代理以控制對這個對象的訪問。 這是專門探索 JavaScript 及其所構建的組件的系列文章的第 19 篇。 如果你錯過了前面的章節,可以在這里找到它們: 想閱讀更多優質文章請...
摘要:它對數組和對象使用按值傳遞,但這是在的共享傳參或拷貝的引用中使用的按值傳參。例如在這里,變量和值在執行期間存儲在堆棧中。返回值這是可選的,函數可以返回值,也可以不返回值。變量被推入堆棧,從而在執行時成為的副本。 這是專門探索 JavaScript 及其所構建的組件的系列文章的第 22 篇。 想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你! 如果你錯過了前面的章節,可...
閱讀 811·2023-04-25 20:18
閱讀 2091·2021-11-22 13:54
閱讀 2527·2021-09-26 09:55
閱讀 3857·2021-09-22 15:28
閱讀 2968·2021-09-03 10:34
閱讀 1709·2021-07-28 00:15
閱讀 1628·2019-08-30 14:25
閱讀 1280·2019-08-29 17:16