亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

IndexedDB瀏覽器內(nèi)建數(shù)據(jù)庫(kù)并行更新問題詳解

 更新時(shí)間:2022年12月29日 10:05:37   作者:莫凡是莫煩  
這篇文章主要為大家介紹了IndexedDB瀏覽器內(nèi)建數(shù)據(jù)庫(kù)并行更新問題詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

IndexedDB 是一個(gè)瀏覽器內(nèi)建的數(shù)據(jù)庫(kù),它比 localStorage 強(qiáng)大得多。

  • 通過支持多種類型的鍵,來存儲(chǔ)幾乎可以是任何類型的值。
  • 支撐事務(wù)的可靠性。
  • 支持鍵值范圍查詢、索引。
  • 和 localStorage 相比,它可以存儲(chǔ)更大的數(shù)據(jù)量。

對(duì)于傳統(tǒng)的 客戶端-服務(wù)器 應(yīng)用,這些功能通常是沒有必要的。IndexedDB 適用于離線應(yīng)用,可與 ServiceWorkers 和其他技術(shù)相結(jié)合使用。

根據(jù)規(guī)范 www.w3.org/TR/IndexedD… 中的描述,IndexedDB 的本機(jī)接口是基于事件的。

我們還可以在基于 promise 的包裝器(wrapper),如 github.com/jakearchiba… 的幫助下使用 async/await。這要方便的多,但是包裝器并不完美,它并不能替代所有情況下的事件。因此,我們先練習(xí)事件(events),在理解了 IndexedDB 之后,我們將使用包裝器。

數(shù)據(jù)在哪兒?

從技術(shù)上講,數(shù)據(jù)通常與瀏覽器設(shè)置、擴(kuò)展程序等一起存儲(chǔ)在訪問者的主目錄中。

不同的瀏覽器和操作系統(tǒng)級(jí)別的用戶都有各自獨(dú)立的存儲(chǔ)。

打開數(shù)據(jù)庫(kù)

要想使用 IndexedDB,首先需要 open(連接)一個(gè)數(shù)據(jù)庫(kù)。

語法:

let openRequest = indexedDB.open(name, version);
  • name —— 字符串,即數(shù)據(jù)庫(kù)名稱。
  • version —— 一個(gè)正整數(shù)版本,默認(rèn)為 1(下面解釋)。

數(shù)據(jù)庫(kù)可以有許多不同的名稱,但是必須存在于當(dāng)前的源(域/協(xié)議/端口)中。不同的網(wǎng)站不能相互訪問對(duì)方的數(shù)據(jù)庫(kù)。

調(diào)用之后會(huì)返回 openRequest 對(duì)象,我們需要監(jiān)聽該對(duì)象上的事件:

  • success:數(shù)據(jù)庫(kù)準(zhǔn)備就緒,openRequest.result 中有了一個(gè)數(shù)據(jù)庫(kù)對(duì)象“Database Object”,我們應(yīng)該將其用于進(jìn)一步的調(diào)用。
  • error:打開失敗。
  • upgradeneeded:數(shù)據(jù)庫(kù)已準(zhǔn)備就緒,但其版本已過時(shí)(見下文)。

IndexedDB 具有內(nèi)建的“模式(scheme)版本控制”機(jī)制,這在服務(wù)器端數(shù)據(jù)庫(kù)中是不存在的。

與服務(wù)器端數(shù)據(jù)庫(kù)不同,IndexedDB 存在于客戶端,數(shù)據(jù)存儲(chǔ)在瀏覽器中。因此,開發(fā)人員無法隨時(shí)都能訪問它。因此,當(dāng)我們發(fā)布了新版本的應(yīng)用程序,用戶訪問我們的網(wǎng)頁(yè),我們可能需要更新該數(shù)據(jù)庫(kù)。

如果本地?cái)?shù)據(jù)庫(kù)版本低于 open 中指定的版本,會(huì)觸發(fā)一個(gè)特殊事件 upgradeneeded。我們可以根據(jù)需要比較版本并升級(jí)數(shù)據(jù)結(jié)構(gòu)。

當(dāng)數(shù)據(jù)庫(kù)還不存在時(shí)(從技術(shù)上講,其版本為 0),也會(huì)觸發(fā) upgradeneeded 事件。因此,我們可以執(zhí)行初始化。

假設(shè)我們發(fā)布了應(yīng)用程序的第一個(gè)版本。

接下來我們就可以打開版本 1 中的 IndexedDB 數(shù)據(jù)庫(kù),并在一個(gè) upgradeneeded 的處理程序中執(zhí)行初始化,如下所示:

let openRequest = indexedDB.open("store", 1);
openRequest.onupgradeneeded = function() {
  // 如果客戶端沒有數(shù)據(jù)庫(kù)則觸發(fā)
  // ...執(zhí)行初始化...
};
openRequest.onerror = function() {
  console.error("Error", openRequest.error);
};
openRequest.onsuccess = function() {
  let db = openRequest.result;
  // 繼續(xù)使用 db 對(duì)象處理數(shù)據(jù)庫(kù)
};

之后不久,我們發(fā)布了第二個(gè)版本。

我們可以打開版本 2 中的 IndexedDB 數(shù)據(jù)庫(kù),并像這樣進(jìn)行升級(jí):

let openRequest = indexedDB.open("store", 2);
openRequest.onupgradeneeded = function(event) {
  // 現(xiàn)有的數(shù)據(jù)庫(kù)版本小于 2(或不存在)
  let db = openRequest.result;
  switch(event.oldVersion) { // 現(xiàn)有的 db 版本
    case 0:
      // 版本 0 表示客戶端沒有數(shù)據(jù)庫(kù)
      // 執(zhí)行初始化
    case 1:
      // 客戶端版本為 1
      // 更新
  }
};

請(qǐng)注意:雖然我們目前的版本是 2,onupgradeneeded 處理程序有針對(duì)版本 0 的代碼分支(適用于初次訪問,瀏覽器中沒有數(shù)據(jù)庫(kù)的用戶)和針對(duì)版本 1 的代碼分支(用于升級(jí))。

接下來,當(dāng)且僅當(dāng) onupgradeneeded 處理程序沒有錯(cuò)誤地執(zhí)行完成,openRequest.onsuccess 被觸發(fā),數(shù)據(jù)庫(kù)才算是成功打開了。

刪除數(shù)據(jù)庫(kù):

let deleteRequest = indexedDB.deleteDatabase(name)
// deleteRequest.onsuccess/onerror 追蹤(tracks)結(jié)果

我們無法使用較舊的 open 調(diào)用版本打開數(shù)據(jù)庫(kù)

如果當(dāng)前用戶的數(shù)據(jù)庫(kù)版本比 open 調(diào)用的版本更高(比如當(dāng)前的數(shù)據(jù)庫(kù)版本為 3,我們卻嘗試運(yùn)行 open(...2),就會(huì)產(chǎn)生錯(cuò)誤并觸發(fā) openRequest.onerror)。

這很罕見,但這樣的事情可能會(huì)在用戶加載了一個(gè)過時(shí)的 JavaScript 代碼時(shí)發(fā)生(例如用戶從一個(gè)代理緩存中加載 JS)。在這種情況下,代碼是過時(shí)的,但數(shù)據(jù)庫(kù)卻是最新的。

為了避免這樣的錯(cuò)誤產(chǎn)生,我們應(yīng)當(dāng)檢查 db.version 并建議用戶重新加載頁(yè)面。使用正確的 HTTP 緩存頭(header)來避免之前緩存的舊代碼被加載,這樣你就永遠(yuǎn)不會(huì)遇到此類問題。

并行更新問題

提到版本控制,有一個(gè)相關(guān)的小問題。

舉個(gè)例子:

  • 一個(gè)用戶在一個(gè)瀏覽器標(biāo)簽頁(yè)中打開了數(shù)據(jù)庫(kù)版本為 1 的我們的網(wǎng)站。
  • 接下來我們發(fā)布了一個(gè)更新,使得代碼更新了。
  • 接下來同一個(gè)用戶在另一個(gè)瀏覽器標(biāo)簽中打開了這個(gè)網(wǎng)站。

這時(shí),有一個(gè)標(biāo)簽頁(yè)和版本為 1 的數(shù)據(jù)庫(kù)建立了一個(gè)連接,而另一個(gè)標(biāo)簽頁(yè)試圖在其 upgradeneeded 處理程序中將數(shù)據(jù)庫(kù)版本升級(jí)到 2。

問題是,這兩個(gè)網(wǎng)頁(yè)是同一個(gè)站點(diǎn),同一個(gè)源,共享同一個(gè)數(shù)據(jù)庫(kù)。而數(shù)據(jù)庫(kù)不能同時(shí)為版本 1 和版本 2。要執(zhí)行版本 2 的更新,必須關(guān)閉對(duì)版本 1 的所有連接,包括第一個(gè)標(biāo)簽頁(yè)中的那個(gè)。

為了解決這一問題,versionchange 事件會(huì)在“過時(shí)的”數(shù)據(jù)庫(kù)對(duì)象上觸發(fā)。我們需要監(jiān)聽這個(gè)事件,關(guān)閉對(duì)舊版本數(shù)據(jù)庫(kù)的連接(還應(yīng)該建議訪問者重新加載頁(yè)面,以加載最新的代碼)。

如果我們不監(jiān)聽 versionchange 事件,也不去關(guān)閉舊連接,那么新的連接就不會(huì)建立。openRequest 對(duì)象會(huì)產(chǎn)生 blocked 事件,而不是 success 事件。因此第二個(gè)標(biāo)簽頁(yè)無法正常工作。

下面是能夠正確處理并行升級(jí)情況的代碼。它安裝了 onversionchange 處理程序,如果當(dāng)前數(shù)據(jù)庫(kù)連接過時(shí)(數(shù)據(jù)庫(kù)版本在其他位置被更新)并關(guān)閉連接,則會(huì)觸發(fā)該處理程序。

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.")
  };
  // ……數(shù)據(jù)庫(kù)已經(jīng)準(zhǔn)備好,請(qǐng)使用它……
};
openRequest.onblocked = function() {
  // 如果我們正確處理了 onversionchange 事件,這個(gè)事件就不應(yīng)該觸發(fā)
  // 這意味著還有另一個(gè)指向同一數(shù)據(jù)庫(kù)的連接
  // 并且在 db.onversionchange 被觸發(fā)后,該連接沒有被關(guān)閉
}; 

……換句話說,在這我們做兩件事:

  • 如果當(dāng)前數(shù)據(jù)庫(kù)版本過時(shí),db.onversionchange 監(jiān)聽器會(huì)通知我們并行嘗試更新。
  • openRequest.onblocked 監(jiān)聽器通知我們相反的情況:在其他地方有一個(gè)與過時(shí)的版本的連接未關(guān)閉,因此無法建立新的連接。

我們可以在 db.onversionchange 中更優(yōu)雅地進(jìn)行處理,提示訪問者在連接關(guān)閉之前保存數(shù)據(jù)等。

或者,另一種方式是不在 db.onversionchange 中關(guān)閉數(shù)據(jù)庫(kù),而是使用 onblocked 處理程序(在瀏覽器新 tab 頁(yè)中)來提醒用戶,告訴他新版本無法加載,直到他們關(guān)閉瀏覽器其他 tab 頁(yè)。

這種更新沖突很少發(fā)生,但我們至少應(yīng)該有一些對(duì)其進(jìn)行處理的程序,至少在 onblocked 處理程序中進(jìn)行處理,以防程序默默卡死而影響用戶體驗(yàn)。

以上就是IndexedDB瀏覽器內(nèi)建數(shù)據(jù)庫(kù)并行更新問題詳解的詳細(xì)內(nèi)容,更多關(guān)于IndexedDB數(shù)據(jù)庫(kù)并行更新的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Navicat快速導(dǎo)入和導(dǎo)出sql文件的方法

    Navicat快速導(dǎo)入和導(dǎo)出sql文件的方法

    Navicat是MySQL非常好用的可視化管理工具,功能非常強(qiáng)大,能滿足我們?nèi)粘?shù)據(jù)庫(kù)開發(fā)的所有需求。今天教大家如何導(dǎo)入和導(dǎo)出SQL文件,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • Navicat15安裝教程超詳細(xì)步驟(最靠譜)

    Navicat15安裝教程超詳細(xì)步驟(最靠譜)

    Navicat是一款輕量級(jí)的用于MySQL連接和管理的工具,非常好用,使用起來方便,簡(jiǎn)潔。下面講講其安裝的過程
    2021-06-06
  • 主鍵與聚集索引

    主鍵與聚集索引

    表通常具有包含唯一標(biāo)識(shí)表中每一行的值的一列或一組列。這樣的一列或多列稱為表的主鍵 (PK),用于強(qiáng)制表的實(shí)體完整性。在創(chuàng)建或修改表時(shí),您可以通過定義 PRIMARY KEY 約束來創(chuàng)建主鍵。
    2009-07-07
  • 分布式緩存Redis與Memcached的優(yōu)缺點(diǎn)區(qū)別比較

    分布式緩存Redis與Memcached的優(yōu)缺點(diǎn)區(qū)別比較

    Redis和Memcached都是基于內(nèi)存key-value的數(shù)據(jù)存儲(chǔ)系統(tǒng)。兩者都可以通過緩存數(shù)據(jù)結(jié)果,HTML片段或其他可能產(chǎn)生成本很高的內(nèi)容來幫助加快應(yīng)用程序的速度。與memcached相比,Redis功能更強(qiáng)大,更受歡迎并且得到更好的支持。
    2022-12-12
  • 從零開始用DataGrip的安裝及使用教程

    從零開始用DataGrip的安裝及使用教程

    這篇文章主要介紹了從零開始用DataGrip的安裝以及使用,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Linux的HBASE數(shù)據(jù)庫(kù)集群部署方法

    Linux的HBASE數(shù)據(jù)庫(kù)集群部署方法

    HBase是一種針對(duì)海量數(shù)據(jù)的key-value型NoSQL數(shù)據(jù)庫(kù),本文詳細(xì)介紹了在Linux系統(tǒng)下HBase的安裝與配置步驟,本文給大家介紹Linux的HBASE數(shù)據(jù)庫(kù)集群部署方法,感興趣的朋友一起看看吧
    2024-10-10
  • OLEDB和ODBC的區(qū)別(優(yōu)缺點(diǎn))

    OLEDB和ODBC的區(qū)別(優(yōu)缺點(diǎn))

    ODBC是一種連接數(shù)據(jù)庫(kù)的開放標(biāo)準(zhǔn),OLEDB(對(duì)象鏈接和嵌入數(shù)據(jù)庫(kù))位于ODBC層與應(yīng)用程序之間. 在你的ASP頁(yè)面里,ADO是位于OLEDB之上的應(yīng)用程序. 你的ADO調(diào)用先被送到OLEDB,然后再交由ODBC處理
    2012-09-09
  • SQL中where和having的區(qū)別詳解

    SQL中where和having的區(qū)別詳解

    這篇文章主要給大家介紹了關(guān)于SQL中where和having區(qū)別的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • MySQL與Oracle 差異比較之一數(shù)據(jù)類型

    MySQL與Oracle 差異比較之一數(shù)據(jù)類型

    這篇文章主要介紹了MySQL與Oracle 差異比較之一數(shù)據(jù)類型,需要的朋友可以參考下
    2017-04-04
  • 使用 Navicat 創(chuàng)建數(shù)據(jù)庫(kù)并用JDBC連接的操作方法

    使用 Navicat 創(chuàng)建數(shù)據(jù)庫(kù)并用JDBC連接的操作方法

    這篇文章主要介紹了使用 Navicat 創(chuàng)建數(shù)據(jù)庫(kù)并用JDBC連接的操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11

最新評(píng)論