【问题标题】:Javascript WebSQL query within for loop. How to know when finished?for 循环中的 Javascript WebSQL 查询。如何知道何时完成?
【发布时间】:2012-10-16 11:26:44
【问题描述】:

我想我有一个相对简单的问题,但我一直在思考,甚至​​谷歌也没有给我一个我可以使用的答案。

基本上,我正在尝试使用 WebSQL 复制一些本地存储的记录。复制不是问题,但我需要知道所有复制操作何时完成,然后我的程序才能继续。

WebSQL 调用是异步的,所以我通常做这些事情的唯一方法是使用回调函数。但是,因为查询是在 for 循环中完成的,所以我不能使用回调函数,因为它会在第一个完成的查询时触发,如代码所示。

代码如下:

function copyRecords(old_parent_id, new_parent_id, callback){
    var db = openDatabase('test', '1.0', 'test', 50 * 1024 * 1024);
    db.transaction(function (tx) {
        tx.executeSql('SELECT * FROM table WHERE parent_id = ?', [old_parent_id], function(tx, results){
            for(var i = 0; i < results.rows.length; i++){
                db.transaction(function (tx2) {
                    tx2.executeSql('INSERT INTO table (name, parent_id) VALUES (?, ?)', [results.rows.item(i).name, new_parent_id], callback);
                })
            }
        });
    });
}

我也试过在i == results.rows.length时调用回调函数,但这并不能保证我所有的查询都完成了。

我想你们中的一些人以前也遇到过同样的问题,因此非常感谢任何有关如何解决此问题并确保仅在 for 循环完成时调用回调函数的帮助。

提前谢谢你。

【问题讨论】:

  • 是否可以通过结果将内部事务移出循环,使INSERT的循环完全进入事务内部?

标签: javascript for-loop web-sql


【解决方案1】:

通常的方法是使用递归异步回调来处理每个单独的记录,而不是 for 循环。

虽然还有更多记录,但异步回调会调用自身。当没有记录时,它可以调用您提供的回调。

以下代码将替换您的内部回调处理程序的内容:

(function nextRecord() {
    var row = results.rows.shift();
    if (row) {
        db.transaction(function (tx2) {
            tx2.executeSql('INSERT INTO table (name, parent_id) VALUES (?, ?)',
                [row.item(i).name, new_parent_id], nextRecord);
       });
    } else {
        callback();
    }
})();

【讨论】:

  • 感谢您的回答!我从没想过使用递归函数!
  • 感谢您的想法,但似乎 web-sql 结果不支持 shift() 函数,因为它不是数组。所以我不得不手动增加一个计数器,它起作用了!
【解决方案2】:

这最好通过记录“回调”函数的执行次数来完成,并且只有在达到结果集的全部数量时才继续。

这是您的修改后的代码:

function copyRecords(old_parent_id, new_parent_id, callback){
    var db = openDatabase('test', '1.0', 'test', 50 * 1024 * 1024);
    db.transaction(function (tx) {
        tx.executeSql('SELECT * FROM table WHERE parent_id = ?', [old_parent_id], function(tx, results){
            if (results.rows.length == 0) 
                callback(); // don't forget this case!
            else {
                var nbrInserted = 0; // This will keep track of how many have been inserted
                for(var i = 0; i < results.rows.length; i++){
                    db.transaction(function (tx2) {
                        tx2.executeSql('INSERT INTO table (name, parent_id) VALUES (?, ?)', [results.rows.item(i).name, new_parent_id], function() {
                            ++nbrInserted; // increment this for every insert
                            if (nbrInserted == results.rows.length) // check if complete
                                callback(); // Do your callback.
                        });
                    });
                }
            }
        });
    });
}

就我而言,我发现 WebSQL 的异步 API 有点繁琐,而且由于 WebSQL 数据库可能会消失(标准已被放弃),我建议大家切换到 SequelSphere。它是一个 HTML5 / JavaScript 关系数据库,适用于所有浏览器和所有平台。它还将数据存储在 localStorage 中,为其提供 WebSQL 的所有好处,而无需任何麻烦。

如果上述解决方案不适合您,请告诉我。

祝你好运!

约翰...

【讨论】:

  • 你真的应该表明你对 SequelSphere 的兴趣。
  • 好点。你是绝对正确的。请原谅...我已连接到 SequelSphere,并且忍不住要拔掉插头。
  • 附注异步回调并不麻烦 - 请参阅我的答案以了解如何做到这一点正确!
  • pps。 async 非常麻烦,而且非常必要。仅我个人意见。我非常喜欢您的答案,但是如果我正确阅读,您的答案会出错,当没有排回来时。
  • 噢! ...触摸...并固定。
猜你喜欢
  • 2015-10-22
  • 1970-01-01
  • 2021-01-19
  • 1970-01-01
  • 1970-01-01
  • 2017-05-30
  • 1970-01-01
  • 2018-10-17
  • 1970-01-01
相关资源
最近更新 更多