<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
IndexedDB 是一個瀏覽器內建的資料庫,它比 localStorage
強大得多。
localStorage
相比,它可以儲存更大的資料量。對於傳統的 使用者端-伺服器 應用,這些功能通常是沒有必要的。IndexedDB 適用於離線應用,可與 ServiceWorkers 和其他技術相結合使用。
根據規範 www.w3.org/TR/IndexedD… 中的描述,IndexedDB 的本機介面是基於事件的。
我們還可以在基於 promise 的包裝器(wrapper),如 github.com/jakearchiba… 的幫助下使用 async/await
。這要方便的多,但是包裝器並不完美,它並不能替代所有情況下的事件。因此,我們先練習事件(events),在理解了 IndexedDB 之後,我們將使用包裝器。
資料在哪兒?
從技術上講,資料通常與瀏覽器設定、擴充套件程式等一起儲存在存取者的主目錄中。
不同的瀏覽器和作業系統級別的使用者都有各自獨立的儲存。
要想使用 IndexedDB,首先需要 open
(連線)一個資料庫。
語法:
let openRequest = indexedDB.open(name, version);
name
—— 字串,即資料庫名稱。version
—— 一個正整數版本,預設為 1
(下面解釋)。資料庫可以有許多不同的名稱,但是必須存在於當前的源(域/協定/埠)中。不同的網站不能相互存取對方的資料庫。
呼叫之後會返回 openRequest
物件,我們需要監聽該物件上的事件:
success
:資料庫準備就緒,openRequest.result
中有了一個資料庫物件“Database Object”,我們應該將其用於進一步的呼叫。error
:開啟失敗。upgradeneeded
:資料庫已準備就緒,但其版本已過時(見下文)。IndexedDB 具有內建的“模式(scheme)版本控制”機制,這在伺服器端資料庫中是不存在的。
與伺服器端資料庫不同,IndexedDB 存在於使用者端,資料儲存在瀏覽器中。因此,開發人員無法隨時都能存取它。因此,當我們釋出了新版本的應用程式,使用者存取我們的網頁,我們可能需要更新該資料庫。
如果本地資料庫版本低於 open
中指定的版本,會觸發一個特殊事件 upgradeneeded
。我們可以根據需要比較版本並升級資料結構。
當資料庫還不存在時(從技術上講,其版本為 0
),也會觸發 upgradeneeded
事件。因此,我們可以執行初始化。
假設我們釋出了應用程式的第一個版本。
接下來我們就可以開啟版本 1
中的 IndexedDB 資料庫,並在一個 upgradeneeded
的處理程式中執行初始化,如下所示:
let openRequest = indexedDB.open("store", 1); openRequest.onupgradeneeded = function() { // 如果使用者端沒有資料庫則觸發 // ...執行初始化... }; openRequest.onerror = function() { console.error("Error", openRequest.error); }; openRequest.onsuccess = function() { let db = openRequest.result; // 繼續使用 db 物件處理資料庫 };
之後不久,我們釋出了第二個版本。
我們可以開啟版本 2
中的 IndexedDB 資料庫,並像這樣進行升級:
let openRequest = indexedDB.open("store", 2); openRequest.onupgradeneeded = function(event) { // 現有的資料庫版本小於 2(或不存在) let db = openRequest.result; switch(event.oldVersion) { // 現有的 db 版本 case 0: // 版本 0 表示使用者端沒有資料庫 // 執行初始化 case 1: // 使用者端版本為 1 // 更新 } };
請注意:雖然我們目前的版本是 2
,onupgradeneeded
處理程式有針對版本 0
的程式碼分支(適用於初次存取,瀏覽器中沒有資料庫的使用者)和針對版本 1
的程式碼分支(用於升級)。
接下來,當且僅當 onupgradeneeded
處理程式沒有錯誤地執行完成,openRequest.onsuccess
被觸發,資料庫才算是成功開啟了。
刪除資料庫:
let deleteRequest = indexedDB.deleteDatabase(name) // deleteRequest.onsuccess/onerror 追蹤(tracks)結果
我們無法使用較舊的 open 呼叫版本開啟資料庫
如果當前使用者的資料庫版本比 open
呼叫的版本更高(比如當前的資料庫版本為 3
,我們卻嘗試執行 open(...2)
,就會產生錯誤並觸發 openRequest.onerror
)。
這很罕見,但這樣的事情可能會在使用者載入了一個過時的 JavaScript 程式碼時發生(例如使用者從一個代理快取中載入 JS)。在這種情況下,程式碼是過時的,但資料庫卻是最新的。
為了避免這樣的錯誤產生,我們應當檢查 db.version
並建議使用者重新載入頁面。使用正確的 HTTP 快取頭(header)來避免之前快取的舊程式碼被載入,這樣你就永遠不會遇到此類問題。
提到版本控制,有一個相關的小問題。
舉個例子:
1
的我們的網站。這時,有一個分頁和版本為 1
的資料庫建立了一個連線,而另一個分頁試圖在其 upgradeneeded
處理程式中將資料庫版本升級到 2
。
問題是,這兩個網頁是同一個站點,同一個源,共用同一個資料庫。而資料庫不能同時為版本 1
和版本 2
。要執行版本 2
的更新,必須關閉對版本 1
的所有連線,包括第一個分頁中的那個。
為了解決這一問題,versionchange
事件會在“過時的”資料庫物件上觸發。我們需要監聽這個事件,關閉對舊版本資料庫的連線(還應該建議存取者重新載入頁面,以載入最新的程式碼)。
如果我們不監聽 versionchange
事件,也不去關閉舊連線,那麼新的連線就不會建立。openRequest
物件會產生 blocked
事件,而不是 success
事件。因此第二個分頁無法正常工作。
下面是能夠正確處理並行升級情況的程式碼。它安裝了 onversionchange
處理程式,如果當前資料庫連線過時(資料庫版本在其他位置被更新)並關閉連線,則會觸發該處理程式。
let openRequest = indexedDB.open("store", 2); openRequest.onupgradeneeded = ...; openRequest.onerror = ...; openRequest.onsuccess = function() { let db = openRequest.result; db.onversionchange = function() { db.close(); alert("Database is outdated, please reload the page.") }; // ……資料庫已經準備好,請使用它…… }; openRequest.onblocked = function() { // 如果我們正確處理了 onversionchange 事件,這個事件就不應該觸發 // 這意味著還有另一個指向同一資料庫的連線 // 並且在 db.onversionchange 被觸發後,該連線沒有被關閉 };
……換句話說,在這我們做兩件事:
db.onversionchange
監聽器會通知我們並行嘗試更新。openRequest.onblocked
監聽器通知我們相反的情況:在其他地方有一個與過時的版本的連線未關閉,因此無法建立新的連線。我們可以在 db.onversionchange
中更優雅地進行處理,提示存取者在連線關閉之前儲存資料等。
或者,另一種方式是不在 db.onversionchange
中關閉資料庫,而是使用 onblocked
處理程式(在瀏覽器新 tab 頁中)來提醒使用者,告訴他新版本無法載入,直到他們關閉瀏覽器其他 tab 頁。
這種更新衝突很少發生,但我們至少應該有一些對其進行處理的程式,至少在 onblocked
處理程式中進行處理,以防程式默默卡死而影響使用者體驗。
以上就是IndexedDB瀏覽器內建資料庫並行更新問題詳解的詳細內容,更多關於IndexedDB資料庫並行更新的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45