You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

未在全局作用域声明变量致IndexedDB报错:db未定义

IndexedDB修改条目时db变量未定义问题修复

问题描述

要实现通过输入框填写值,提交修改IndexedDB中已有条目,且后续可检索再次编辑的功能,但运行时报错:Uncaught TypeError: db is undefined。点击按钮触发$('#edit-button').click函数,该函数调用updateMarma,而updateMarma依赖getObjectStore函数,后者需要已声明的db变量。

最初将所有代码放在open.onsuccess = function() {}内时db可正常访问,但为了让函数能独立调用移到外部后,无法正确声明和维护db变量。尝试在open.onupgradeneeded内赋值db = open.result;以及使用IIFE都未解决问题。

问题根源

  1. 局部变量覆盖外层变量:在open.onsuccess回调中使用var db = open.result;重新声明了局部db变量,导致外层IIFE中声明的db始终未被赋值,一直处于undefined状态。
  2. 数据库过早关闭:初始化数据完成后调用db.close()关闭了数据库连接,后续操作时db已失效。
  3. 事务与存储对象管理不当:updateMarma中尝试复用store变量,不符合IndexedDB事务的生命周期规则,应该每次操作都创建新的事务。

修改后的完整代码

(function() {
    var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB;
    var db; // 外层的db变量,供所有函数访问

    // 打开(或创建)数据库
    var open = indexedDB.open("marmaDB", 1);
    console.log("打开数据库...");

    // 创建数据库 schema
    console.log("创建数据库结构...");
    open.onupgradeneeded = function(e) {
        db = e.target.result; // 给外层db赋值
        var store = db.createObjectStore("marmasStore", {keyPath: "id"});
        store.createIndex("NameIndex", ["name.last", "name.first"]);
        store.createIndex('sanskrit', 'sanskrit', { unique: false });
        store.createIndex('name', 'name', { unique: false });
        store.createIndex('marmaGrp', 'marmaGrp', { unique: false });
        store.createIndex('location', 'location', { unique: false });
        store.createIndex('localisation', 'localisation', { unique: false });
        store.createIndex('awareness', 'awareness', { unique: false });
        store.createIndex('frequency', 'frequency', { unique: false });
    };

    // 获取对象存储(事务)
    function getObjectStore(store_name, mode) {
        if (!db) {
            console.error("数据库未连接");
            return null;
        }
        var tx = db.transaction(store_name, mode);
        tx.onerror = function(e) {
            console.error("事务错误:", e.target.error);
        };
        return tx.objectStore(store_name);
    }

    // 数据库打开成功回调
    open.onsuccess = function(e) {
        console.log("数据库打开成功");
        db = e.target.result; // 给外层db赋值,覆盖可能的onupgradeneeded中的赋值

        // 初始化数据(仅在数据库新建或版本升级时执行,可根据需求调整)
        var tx = db.transaction("marmasStore", "readwrite");
        var store = tx.objectStore("marmasStore");
        
        // 先检查是否已有数据,避免重复初始化
        store.count().onsuccess = function(countEvt) {
            if (countEvt.target.result === 0) {
                const initialMarmaData = [
                    { id: "ani_ll", sanskrit: "ani", name: "Ani", marmaGrp: "snayu", location: "linker Oberschenkel", localisation: 0, awareness: 0, frequency: 0 },
                    { id: "ani_rl", sanskrit: "ani", name: "Ani", marmaGrp: "snayu", location: "rechter Oberschenkel", localisation: 0, awareness: 0, frequency: 0 },
                    { id: "ani_la", sanskrit: "ani", name: "Ani", marmaGrp: "snayu", location: "linker Arm", localisation: 0, awareness: 0, frequency: 0 },
                    { id: "ani_ra", sanskrit: "ani", name: "Ani", marmaGrp: "snayu", location: "rechter Arm", localisation: 0, awareness: 0, frequency: 0 },
                ];

                console.log("初始化数据库数据...");
                initialMarmaData.forEach((marma) => {
                    var request = store.put(marma);
                    request.onsuccess = (event) => {
                        console.log(event.target.result + " 数据初始化完成");
                    };
                    request.onerror = (event) => {
                        console.error("初始化数据失败:", event.target.error);
                    };
                });
            }
        };

        tx.oncomplete = function() {
            console.log("初始化事务完成");
            // 不再关闭数据库,保持连接供后续操作使用
        };

        tx.onerror = function(e) {
            console.error("初始化事务错误:", e.target.error);
        };
    };

    // 数据库打开失败回调
    open.onerror = function(e) {
        console.error("数据库打开失败:", e.target.error);
    };

    // 更新Marma条目
    function updateMarma(key) {
        console.log("更新Marma:", key);
        var store = getObjectStore("marmasStore", 'readwrite');
        if (!store) return;

        var marmaInfo = store.get(key);
        marmaInfo.onsuccess = function(evt) {
            var record = evt.target.result;
            console.log("找到记录:", record);
            if (!record) {
                alert("未找到匹配的记录");
                return;
            }

            // 获取输入框的新值并更新记录
            record.location = $('#bodylocation').val();
            record.awareness = parseInt($('#awareness').val(), 10);

            // 保存更新后的记录
            var updateRequest = store.put(record);
            updateRequest.onsuccess = function() {
                alert("ID " + record.id + " 更新成功");
                console.log("记录更新成功:", record);
            };
            updateRequest.onerror = function(e) {
                console.error("更新记录失败:", e.target.error);
                alert("更新失败,请查看控制台日志");
            };
        };
        marmaInfo.onerror = function(e) {
            console.error("获取记录失败:", e.target.error);
            alert("获取记录失败,请查看控制台日志");
        };
    }

    // 编辑按钮点击事件
    $('#edit-button').click(function(evt) {
        evt.preventDefault();
        console.log("触发编辑操作");
        var key = $('#marmaID').val().trim();
        var new_bodylocation = $('#bodylocation').val().trim();
        var new_awareness = $('#awareness').val().trim();

        if (!key) {
            alert("请输入有效的Marma ID");
            return;
        }
        if (!new_bodylocation || isNaN(new_awareness)) {
            alert("请填写有效的更新值");
            return;
        }

        console.log("正在编辑:", key);
        updateMarma(key);
    });

})(); 

关键修改说明

  1. 正确赋值外层db变量:在open.onupgradeneeded和open.onsuccess中,直接给外层的db赋值(去掉var),确保所有函数能访问到有效的数据库实例。
  2. 保留数据库连接:移除初始化后的db.close(),保持数据库连接打开,供后续编辑操作使用。
  3. 完善事务与错误处理:为事务和请求添加onerror回调,便于排查问题;每次更新操作创建新的事务,符合IndexedDB的使用规范。
  4. 补充更新逻辑:在updateMarma中加入获取输入框新值、更新记录并保存到数据库的逻辑,完成完整的修改流程。
  5. 初始化数据判断:添加数据数量检查,避免每次打开数据库都重复初始化数据。

内容的提问来源于stack exchange,提问作者Corbinian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 12:02:10