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

JS嵌套while循环时IndexedDB异步回调失效致无限循环

问题

我写了一段JS脚本,用来检查数据库里是否存在指定值:如果不存在就填充数据库;再次触发时从数据库读取值并展示在页面上。刷新页面执行两次脚本时功能正常,但把逻辑放进while循环后直接失效,循环无限运行。我猜是没法进入marmaInfo.onsuccess = function(evt) {}回调,不确定是不是作用域问题,搞不懂加了while循环后行为为啥差这么多。

相关代码:

var key = $('#marmaID').val();
console.log("key " + key );
store = getObjectStore("marmasStore", 'readwrite');

let i = 0;
//while (i < 1) {
    var marmaInfo = store.get(key);
    marmaInfo.onsuccess = function(evt) {
        var req = store.openCursor(key);
        var record = evt.target.result;
        console.log("record:", record);
        req.onsuccess = function(e) {
          var cursor = e.target.result; 
          if (cursor !== null) { // key already exist
            console.log(key + " FOUND");
            console.log("load and display values of " + key);
            data = marmaInfo.result
            //build page
            // Marma information
            document.getElementById("headline").innerHTML = data.sanskrit;
            console.log("display values of " + key + " DONE");
            i++;
          } else { // key not exist
            console.log(key + " NOT FOUND");
            console.log("initial filling DB ...");
            initialMarmaData.forEach((marma) => {
                var request = store.put(marma);
                request.onsuccess = (event) => {
                    console.log(event.target.result + " initial filling DB DONE");
                };
            //return;
            });
            //store.add(obj)
          }
        };
    };
    marmaInfo.onerror = function(evt) {
        console.log("error");
        i++;    
    }
//}
原因与解决办法

核心问题:IndexedDB是异步操作,while是同步阻塞循环

IndexedDB的所有操作(比如store.get()、store.openCursor())都是异步非阻塞的,它们的回调函数(onsuccess/onerror)会在当前同步代码执行完之后,才会进入事件队列等待执行。

你加的while (i < 1)是同步阻塞循环,会一直占用主线程,导致所有IndexedDB的回调根本没机会执行——主线程被while死死占着,事件队列里的回调永远轮不到,自然i永远不会被修改,循环就无限跑下去了。

修正方案:用异步逻辑替代同步while循环

不需要用while循环,直接利用IndexedDB的异步回调逻辑来控制流程就行。如果确实需要重复执行直到满足条件,应该用递归调用或者Promise封装来实现异步循环,而不是同步while。

优化后的代码示例:

var key = $('#marmaID').val();
console.log("key " + key );
store = getObjectStore("marmasStore", 'readwrite');

// 封装成异步函数,避免同步阻塞
function checkAndProcessMarma() {
    var marmaInfo = store.get(key);
    marmaInfo.onsuccess = function(evt) {
        var req = store.openCursor(key);
        var record = evt.target.result;
        console.log("record:", record);
        req.onsuccess = function(e) {
          var cursor = e.target.result; 
          if (cursor !== null) { // 已存在该key
            console.log(key + " FOUND");
            console.log("加载并展示" + key + "的数据");
            const data = marmaInfo.result;
            // 渲染页面
            document.getElementById("headline").innerHTML = data.sanskrit;
            console.log("展示" + key + "的数据完成");
          } else { // 不存在该key
            console.log(key + " NOT FOUND");
            console.log("开始初始化填充数据库...");
            // 用Promise.all等待所有put操作完成,确保数据写入后再进行后续逻辑
            const putPromises = initialMarmaData.map(marma => {
                return new Promise((resolve, reject) => {
                    var request = store.put(marma);
                    request.onsuccess = (event) => {
                        console.log(event.target.result + " 初始化写入完成");
                        resolve();
                    };
                    request.onerror = reject;
                });
            });
            // 所有数据写入后,重新检查并展示数据
            Promise.all(putPromises).then(() => {
                console.log("全部初始化数据写入完成");
                checkAndProcessMarma();
            }).catch(err => {
                console.error("初始化写入失败:", err);
            });
          }
        };
    };
    marmaInfo.onerror = function(evt) {
        console.log("查询出错");
    }
}

// 启动流程
checkAndProcessMarma();

关键优化点:

  • 把逻辑封装成异步函数,避免同步阻塞主线程
  • 用Promise.all等待所有数据库写入操作完成,确保数据落地后再重新查询
  • 去掉了无意义的i变量,改用异步回调的流程控制替代同步while循环

内容的提问来源于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 01:53:12