国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

IndexedDB使用與出坑指南

陳偉 / 2723人閱讀

摘要:在不指定的情況下,默認版本號為。具體示例如下在需要更新數據庫的模式時,需要更新版本號。此時我們指定一個高于之前版本的版本號,就會觸發事件。數據操作事務在中,我們也能夠使用事務來進行數據庫的操作。

概述

本文通過對IndexedDB的使用方法和使用場景進行相關介紹,對常見的問題進行解答。

同時,因為MDN中的相關文檔缺乏相關邏輯性,所以不容易理解。本文將通過項目中常見的數據存儲和操作需求來進行內容組織。

讀者能夠通過本文學會在項目中正確的使用IndexedDB,給應用帶來的本地存儲能力,并且避免一些常見的問題。

原因:開發者需要在本地進行永久存儲

當我們進行一些較大的SPA頁面開發時,我們會需要進行一些數據的本地存儲。

當數據量不大時,我們可以通過SessionStorage或者LocalStorage來進行存儲,但是當數據量較大,或符合一定的規范時,我們可以使用數據庫來進行數據的存儲。

在瀏覽器提供的數據庫中,共有web sqlIndexedDB兩種。相較于HTML5已經廢棄的web sql來說,更推薦大家使用IndexedDB

結構

下面,我們通過一張圖來了解下,IndexedDB整體的結構。

類比sql型數據庫,IndexedDB中的DB(數據庫)就是sql中的DB,而Object Store(存儲空間)則是數據表,Item則等于表中的一條記錄。

使用IndexedDB

現在,我們將其根據IndexedDB的結構來對其操作進行介紹,能讓大家對這個存儲空間有一個初步的了解。我們主要介紹:

數據庫操作

數據表操作

數據操作

數據庫操作 創建或打開數據庫

使用IndexedDB第一步,就是創建或打開一個數據庫。我們使用window.indexedDB.open(DBName)這個API來打進行操作。具體示例如下:

const request = window.indexedDB.open("test");

request.onupgradeneeded = function (event) {
    
}

request.onsuccess = function(event) {
    //request === event.target;
}
request.onerror = function(event) {}

調用此接口時,如果當前數據庫不存在,則會創建一個新的數據庫。

當數據庫建立連接時,會返回一個IDBOpenDBRequest對象。

在連接建立成功時,會觸發onsuccess事件,其中函數參數eventtarget屬性就是request對象。

而在數據庫創建或者版本更新時,會觸發onupgradeneeded事件。

更新數據庫版本號

window.indexedDB.open的第二個參數即為版本號。在不指定的情況下,默認版本號為1。具體示例如下:

const request = window.indexedDB.open("test", 2);

在需要更新數據庫的schema(模式)時,需要更新版本號。此時我們指定一個高于之前版本的版本號,就會觸發onupgradeneeded事件。類似的,當此數據庫不存在時,也會觸發此事件并且將版本更新到置頂版本。

我們需要注意的是,版本號是一個Unsigned long long數字,這意味著它可以是一個非常大的整數。但是,它不能是一個小數,否則它將會被轉為最近的整數,同時有可能導致onUpgradeneeded事件不觸發(bug)。

存儲空間操作 創建存儲空間

我們使用createObjectStore來創建一個存儲空間。同時,使用createIndex來創建它的索引。具體示例如下:

var request = window.indexedDB.open("test", 1);

request.onupgradeneeded = function (event) {
    var db = event.target.result;
    var objectStore = db.createObjectStore("table1", {keyPath: "id", autoIncrement: true});

    objectStore.createIndex("name", "name", {unique: false});
}

request.onerror = function (event) {
    alert("Why didn"t you allow my web app to use IndexedDB?!");
};

注:只能在onupgradeneeded回調函數中創建存儲空間,而不能在數據庫打開后的success回調函數中創建。

通過createObjectStore能夠創建一個存儲空間。接受兩個參數:

第一個參數,存儲空間的名稱,即我們上面的customers。

第二個參數,指定存儲的keyPath值為存儲對象的某個屬性,這個屬性能夠在獲取存儲空間數據的時候當做key值使用。autoIncrement指定了key值是否自增(當key值為默認的從1開始到2^53的整數時)。

createIndex能夠給當前的存儲空間設置一個索引。它接受三個參數:

第一個參數,索引的名稱。

第二個參數,指定根據存儲數據的哪一個屬性來構建索引。

第三個屬性, options對象,其中屬性unique的值為true表示不允許索引值相等。

數據操作 事務

IndexedDB中,我們也能夠使用事務來進行數據庫的操作。事務有三個模式(常量已經棄用):

readOnly,只讀。

readwrite,讀寫。

versionchange,數據庫版本變化。

我們創建一個事務時,需要從上面選擇一種模式,如果不指定的話,則默認為只讀模式。具體示例如下:

const transaction = db.transaction(["customers"], "readwrite");

事務函數transaction的第一個參數為需要關聯的存儲空間,第二個可選參數為事務模式。與上面類似,事務成功時也會觸發onsuccess函數,失敗時觸發onerror函數。

事務的操作都是原子性的。

增加數據

當存儲空間初始化完成后,我們可以把數據放入存儲空間中。直接調用add方法就可以將數據放入存儲空間內,具體示例如下:

var request = window.indexedDB.open("test", 1);

request.onsuccess = function (event) {
    var db = event.target.result;

    var transaction = db.transaction(["table1"], "readwrite");

    var objectStore = transaction.objectStore("table1");

    var index = objectStore.index("name");

    objectStore.add({name: "a", age: 10});
    objectStore.add({name: "b", age: 20});
}

注:add方法中的第二個參數key值是指定存儲空間中的keyPath值,如果data中包含keyPath值或者此值為自增值,那么可以略去此參數。

查找數據 通過特定值獲取數據

當我們需要從存儲空間獲取數據時,我們可以通過以下的方法:

var request = window.indexedDB.open("test", 1);

request.onsuccess = function (event) {
    var db = event.target.result;

    var transaction = db.transaction(["table1"], "readwrite");

    var objectStore = transaction.objectStore("table1");

    var request = objectStore.get(1);

    request.onsuccess = function (event) {
        // 對 request.result 做些操作!
        console.log(request.result);
    };

    request.onerror = function (event) {
        // 錯誤處理!
    };
}
通過游標獲取數據

當你需要便利整個存儲空間中的數據時,你就需要使用到游標。游標使用方法如下:

var request = window.indexedDB.open("test", 1);

request.onsuccess = function (event) {
    var db = event.target.result;

    var transaction = db.transaction(["table1"], "readwrite");

    var objectStore = transaction.objectStore("table1");

    var request = objectStore.openCursor();

    request.onsuccess = function (event) {
        var cursor = event.target.result;
        if (cursor) {
            // 使用Object.assign方法是為了避免控制臺打印時出錯
            console.log(Object.assign(cursor.value));
            cursor.continue();
        }
    };

    request.onerror = function (event) {
        // 錯誤處理!
    };
}

使用游標時有一個需要注意的地方,當游標便利整個存儲空間但是并未找到給定條件的值時,仍然會觸發onsuccess函數。

openCursoropenKeyCursor有兩個參數:

第一個參數,遍歷范圍,指定游標的訪問范圍。該范圍通過一個IDBKeyRange參數的方法來獲取。

遍歷范圍參數具體示例如下:

// 匹配值 key === 1
const singleKeyRange = IDBKeyRange.only(1);

// 匹配值 key >= 1
const lowerBoundKeyRange = IDBKeyRange.lowerBound(1);

// 匹配值 key > 1
const lowerBoundOpenKeyRange = IDBKeyRange.lowerBound(1, true);

// 匹配值 key < 2
const upperBoundOpenKeyRange = IDBKeyRange.upperBound(2, true);

// 匹配值 key >= 1 && key < 2
const boundKeyRange = IDBKeyRange.bound(1, 2, false, true);

index.openCursor(boundKeyRange).onsuccess = function(event) {
  const cursor = event.target.result;
  if (cursor) {
    // Do something with the matches.
    cursor.continue();
  }
};

?

第二個參數,便利順序,指定游標便利時的順序和處理相同id(keyPath屬性指定字段)重復時的處理方法。改范圍通過特定的字符串(IDBCursor的常量已經棄用)來獲取。其中:

next,從前往后獲取所有數據(包括重復數據)

prev,從后往前獲取所有數據(包括重復數據)

nextunique,從前往后獲取數據(重復數據只取第一條,索引重復即認為重復,下同)

prevunique,從后往前獲取數據(重復數據只取第一條)

遍歷順序參數具體示例如下:

var request = window.indexedDB.open("test", 1);

request.onsuccess = function (event) {
    var db = event.target.result;

    var transaction = db.transaction(["table1"], "readwrite");

    var objectStore = transaction.objectStore("table1");

    var lowerBoundOpenKeyRange = IDBKeyRange.lowerBound(1, false);
    var request = objectStore.openCursor(lowerBoundOpenKeyRange, IDBCursor.PREV);

    request.onsuccess = function (event) {
        var cursor = event.target.result;
        if (cursor) {
            // 使用Object.assign方法是為了避免控制臺打印時出錯
            console.log(Object.assign(cursor.value));
            cursor.continue();
        }
    };

    request.onerror = function (event) {
        // 錯誤處理!
    };
}
使用索引

在前面構建數據庫時,我們創建了兩個索引?,F在我們也可以通過索引來進行數據檢索。他的本質還是通過之前獲取數據的API來進行,只是將原來使用的keyPath屬性轉換成為了索引指定的屬性。具體示例如下:

var request = window.indexedDB.open("test", 1);

request.onsuccess = function (event) {
    var db = event.target.result;

    var transaction = db.transaction(["table1"], "readwrite");

    var objectStore = transaction.objectStore("table1");

    var index = objectStore.index("name");

    // 第一種,get方法
    index.get("a").onsuccess = function (event) {
        console.log(event.target.result);
    }

    // 第二種,普通游標方法
    index.openCursor().onsuccess = function (event) {
        console.log("openCursor:", event.target.result.value);
    }

    // 第三種,鍵游標方法,該方法與第二種的差別為:普通游標帶有value值表示獲取的數據,而鍵游標沒有
    index.openKeyCursor().onsuccess = function (event) {
        console.log("openKeyCursor:", event.target.result);
    }
}
修改數據

當需要修改存儲空間中的數據時,我們可以使用以下的API:

var objectStore = transaction.objectStore("customers");

var request = objectStore.put(data);

request.onsuccess = function (event) {
    
}

注:put方法不僅能夠修改現有數據,也能夠往存儲空間中增加新的數據。

刪除數據

當我們需要刪除已經無用的數據時,我們可以通過以下方法:

var objectStore = transaction.objectStore("customers");

var request = objectStore.delete(name);

request.onsuccess = function (event) {
    
}
異常處理

在瀏覽器有如下操作的情況下,indexedDB可能會出現異常:

用戶清除瀏覽器緩存

存儲空間超過大小限制

此時,需要對錯誤進行捕獲,并且對用戶進行提示。此章節不是本文重點,再此略過。

擴展須知 取值相關 key值能夠接受的數據類型

IndexedDB中,鍵值對中的key值可以接受以下幾種類型的值:

number

data

string

binary

array

具體說明可以見文檔此處。

key path能夠接受的數據類型

當一個key值變為主鍵,即keyPath時,它的值就只能是以下幾種:

Blob

File

Array

String

注:空格不能出現在key path中。

具體說明可以見文檔此處。

value能夠接受的數據類型

IndexedDB中,value能夠接受ECMA-262中所有的類型的值,例如String,Date,ImageDate等。

事務相關 事務中斷后,會不會影響key值的自增

IndexedDB在沒有指定key值的時候就會采用自增的key值。如果一個事務在中途中斷,那么key值的自增將會從中斷的事務開始前的key開始。

安全相關

IndexedDB也受到瀏覽器同源策略的限制。

用戶相關 清空緩存

用戶在清除瀏覽器緩存時,可能會清除IndexedDB中相關的數據。

訪問權限

部分瀏覽器如Safari手機版隱私模式在訪問IndexedDB時,可能會出現由于沒有權限而導致的異常(LocalStorage也會),需要進行異常處理。

總結

IndexedDB在本地存儲中有著無可替代的作用,是替代關系型數據庫web sql的產品,能夠對大量數據進行存儲。在許多需要運用離線存儲的場景下,它能夠給我們提供有效的支撐。

但是,IndexedDB在使用過程中仍然需要避免可能會出現的一些問題,或者對可能導致的不利影響有一定的容錯處理。這樣才不會對應用產生重大影響。

參考文獻

瀏覽器的同源策略

使用indexedDB MDN入門

IndexedDB API參考

W3C IndexedDB 2.0規范

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/80378.html

相關文章

  • PDO擴展PDO::ATTR_AUTOCOMMIT 出坑

    摘要:問題描述我自己以擴展為基礎,封裝了一個異步任務服務器框架,數據庫操作使用擴展,但是在插入數據的時候,出現了異常情況,具體狀況如下表引擎的正常插入,沒有問題表引擎查詢都可以的,但是插入失敗,出現回滾現象,字段變化,表的變化,正常返回解決過程監 問題描述 我自己以swoole擴展為基礎,封裝了一個異步任務服務器框架,數據庫操作使用pdo擴展,但是在插入數據的時候,出現了異常情況,具體狀況如...

    Binguner 評論0 收藏0
  • 總要先爬出坑的JEE架構

    摘要:只要滿足規范的放入該容器,馬上就會被容器進行高效率的管理。根據康威定律,設計系統的組織時,最終產生的設計等價于組織的溝通結構,通俗來講,團隊的交流機制應該與架構分層交互機制相對應。 本博客 貓叔的博客,轉載請申明出處 先來看看官網對它的定義。 Java平臺企業版(Java EE)是社區驅動的企業軟件的標準。Java EE是使用Java Community Process開發的,其中包括...

    Coding01 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<