发布于 2026-01-05 5 阅读
0

让网站离线也能运行——离线存储。让 IndexedDB 成为英雄!实现示例用例?

让网站离线也能运行——离线存储。让 IndexedDB 成为关键!

执行

例子

应用场景?

注意:本文不假设您已了解第一部分的任何内容。

传统上,Cookie 用于存储本地数据。但随着 HTML5 API 的出现,我们有了新的选择,例如 DataFrame localStoragesessionStorageDatabase、WebSQLDatabase 和IndexedDBDataFrame。本文将重点讨论 IndexedDB。

假设你已经完成了 Service Worker 的配置,现在你的网站可以在离线状态下加载。但是……如果你想存储和检索特定数据怎么办?fetch()由于用户处于离线状态,你不能直接通过 API 来实现。

在这种情况下,您可以将数据存储在 IndexedDB 中!

索引数据库API(Indexed Database API)是由Web浏览器提供的一种JavaScript应用程序编程接口,用于管理JSON对象的NoSQL数据库。它是由万维网联盟(W3C)维护的标准。

~维基百科

IndexedDB 由浏览器提供,因此无需联网即可执行 CRUD(创建、读取、更新、删除)操作。它类似于 Android 中的 SQLite(只是不包含 SQL 语句)。

执行

如果您更喜欢通过 codesandbox 自学,可以查看IndexedDB 示例

对于使用前缀的浏览器,我们可以从类似这样的内容开始:

window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction || {READ_WRITE: "readwrite"};
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;

if (!window.indexedDB) {
    console.log("Your browser doesn't support a stable version of IndexedDB. Such and such feature will not be available.");
}
Enter fullscreen mode Exit fullscreen mode

在继续讲解下一段代码之前,我想先提醒大家一点:IndexedDB 本身并没有使用Promise,因此它很大程度上依赖于onsuccess回调onerror函数。虽然有一些库(例如idb)提供了 Promise 化的 IndexedDB 版本,但本文将使用原生的 IndexedDB 代码。

打开/创建数据库

打开数据库时,如果数据库不存在,则会自动创建新数据库。

let db;
const request = indexedDB.open("MyTestDatabase");
request.onsuccess = function(event) {
    db = event.target.result;
};

Enter fullscreen mode Exit fullscreen mode

定义模式/值

创建新数据库时,onupgradeneeded会触发该事件。我们可以在这里创建对象存储。

request.onupgradeneeded = function() {
    const db = event.target.result;
    const userObjectStore = db.createObjectStore("users", {keyPath: "userid"});
    userObjectStore.createIndex("name", "name", { unique: false });
    userObjectStore.createIndex("email", "email", { unique: true });
}
Enter fullscreen mode Exit fullscreen mode

因此,创建/打开数据库的完整代码大致如下所示:

async function openDatabase() {
    return new Promise((resolve, reject) => {
        const request = indexedDB.open("MyTestDatabase");
        request.onsuccess = function(event) {
            resolve(event.target.result);
        }

        request.onupgradeneeded = function() {
            const db = event.target.result;
            const userObjectStore = db.createObjectStore("users", {keyPath: "userid"});
            userObjectStore.createIndex("name", "name", { unique: false });
            userObjectStore.createIndex("email", "email", { unique: true });
        }       
    }) 
}

openDatabase()
    .then(db => {
        // db instance accessible here

    })
Enter fullscreen mode Exit fullscreen mode

添加数据

现在我们已经可以db在 Promise 中访问对象了openDatabase()。我们可以使用此对象向 IndexedDB 添加/读取/删除数据。

(async function() {
    const db = await openDatabase();

    // Add
    const userReadWriteTransaction = db.transaction("users", "readwrite");
    const newObjectStore = userReadWriteTransaction.objectStore("users");

    newObjectStore.add({
        userid: "4",
        name: "John Doe",
        email: "josn@gmail.com"
    });

    userReadWriteTransaction.onsuccess = function(e) {
        console.log("Data Added");
    }

})();
Enter fullscreen mode Exit fullscreen mode

数据

const request = db.transaction("users", "readwrite")
    .objectStore("users")
    .delete("4");

request.onsuccess = function(event) {
    console.log("Deleted!");
};
Enter fullscreen mode Exit fullscreen mode

读取和更新数据

const readTransaction = db.transaction(["users"]);
const objectStore = transaction.objectStore("customers");
const request = objectStore.get("4");

request.onsuccess = function(event) {
    console.log("User is " + request.result.name);
    const data = event.target.result;
    data.name = "John Doe";

    const updateRequest = objectStore.put(data);
    updateRequest.onsuccess = function(event) {
        console.log("Data Updated!");
    }
};
Enter fullscreen mode Exit fullscreen mode

例子

应用场景?

  1. 如果你的 API 总是(或大多数时候)返回相同的值,你可以调用 API,将响应存储在 IndexedDB 中,下次用户调用 API 时,你可以直接从 IndexedDB 返回该值,之后或许可以再次调用 API 并存储更新后的值。

  2. 我的应用PocketBook使用了 IndexedDB,它是 Google Keep 的替代品,可以用来存储待办事项、目标等等。PocketBook 默认使用 IndexedDB 来存储笔记本信息。因此,即使离线也可以使用 PocketBook!


MDN 文档: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB
CodeSandbox 示例: https://codesandbox.io/s/indexeddb-example-trv2f
PocketBook: https: //pocketbook.cc


感谢阅读!如果您有任何使用 IndexedDB 的有趣项目,请在下方留下链接!

文章来源:https://dev.to/saurabhdaware/make-websites-work-offline-offline-storage-making-indexeddb-the-hero-1oee