使用IndexedDB和setInterval实现跨标签页通信

209 阅读2分钟

引言

在现代Web开发中,我们经常需要在不同的标签页或窗口之间共享数据。IndexedDB提供了一种在客户端存储大量结构化数据的方法,并且可以通过定时器轮询的方式实现跨标签页的通信。本文将介绍如何使用IndexedDB和setInterval来实现这一功能。

IndexedDB简介

IndexedDB是一个运行在浏览器中的非关系型数据库,它允许我们存储和检索大量结构化数据。与传统的本地存储解决方案(如localStorage)相比,IndexedDB提供了更复杂的查询功能,并且可以存储二进制数据。

实现跨标签页通信

为了实现跨标签页通信,我们可以利用IndexedDB的数据库实例在不同标签页间共享的特性。通过在每个标签页中轮询数据库,我们可以检测到其他标签页对数据库所做的更改,并相应地更新当前标签页的数据。

示例代码

以下是实现跨标签页通信的示例代码,包括HTML和JavaScript部分。

HTML代码

我们有两个HTML文件:index.html用于添加学生信息,index2.html用于显示学生信息。

<!-- index.html -->
<body>
    <h1>新增学生</h1>
    <div>
        <span>学生学号:</span>
        <input type="text" name="stuId" id="stuId">
    </div>
    <div>
        <span>学生姓名:</span>
        <input type="text" name="stuName" id="stuName">
    </div>
    <div>
        <span>学生年龄:</span>
        <input type="text" name="stuAge" id="stuAge">
    </div>
    <button id="addBtn">新增学生</button>
    <script src="./db.js"></script>
    <script>
        openDB('stuDB', 1)
            .then((db) => {
                document.getElementById("addBtn").onclick = function () {
                    addData(db, "stu", { "stuId": stuId.value, "stuName": stuName.value, "stuAge": stuAge.value });
                    stuId.value = stuName.value = stuAge.value = "";
                }
            })
    </script>
</body>
<!-- index2.html -->
<body>
    <h1>学生表</h1>
    <table id="tab"></table>
    <script src="./db.js"></script>
    <script>
        function render(arr) {
            let tab = document.querySelector("#tab");
            tab.innerHTML = `
                <tr>
                    <td>学号</td>
                    <td>姓名</td>
                    <td>年龄</td>
                </tr>
            `;
            var str = arr.map((item) => {
                return `
                    <tr>
                        <td>${item.stuId}</td>
                        <td>${item.stuName}</td>
                        <td>${item.stuAge}</td>
                    </tr>
                `
            }).join("");
            tab.innerHTML += str;
        }
​
        async function renderTable() {
            let db = await openDB('stuDB', 1);
            let stuInfo = await getDataByKey(db, "stu");
            render(stuInfo);
​
            setInterval(async function () {
                let stuInfo2 = await getDataByKey(db, "stu");
                if (stuInfo2.length !== stuInfo.length) {
                    stuInfo = stuInfo2;
                    render(stuInfo);
                }
            }, 1000);
        }
        renderTable();
    </script>
</body>

JavaScript代码

db.js文件包含了操作IndexedDB的函数。

function openDB(dbName, version = 1) {
    return new Promise((resolve, reject) => {
        var db;
        const request = indexedDB.open(dbName, version);
        request.onsuccess = function (event) {
            db = event.target.result;
            console.log("数据库打开成功");
            resolve(db);
        };
        request.onerror = function (event) {
            console.log("数据库打开报错");
        };
        request.onupgradeneeded = function (event) {
            db = event.target.result;
            var objectStore = db.createObjectStore("stu", { keyPath: "stuId", autoIncrement: true });
            objectStore.createIndex("stuId", "stuId", { unique: true });
            objectStore.createIndex("stuName", "stuName", { unique: false });
            objectStore.createIndex("stuAge", "stuAge", { unique: false });
        };
    });
}
​
function addData(db, storeName, data) {
    var request = db.transaction([storeName], "readwrite").objectStore(storeName).add(data);
    request.onsuccess = function (event) {
        console.log("数据写入成功");
    };
    request.onerror = function (event) {
        console.log("数据写入失败");
    };
}
​
function getDataByKey(db, storeName) {
    return new Promise((resolve, reject) => {
        var transaction = db.transaction([storeName]);
        var objectStore = transaction.objectStore(storeName);
        var request = objectStore.getAll();
        request.onerror = function (event) {
            console.log("事务失败");
        };
        request.onsuccess = function (event) {
            resolve(request.result);
        };
    });
}

总结

通过上述代码,我们可以实现在不同标签页之间共享和更新学生信息。这种方法利用了IndexedDB的持久性存储和定时器轮询的实时性,为跨标签页通信提供了一种有效的解s决方案。