8

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

基本上我正在尝试复制一些使用 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);
                })
            }
        });
    });
}

我也尝试过调用回调函数 when i == results.rows.length,但这并不能确保所有查询都已完成。

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

先感谢您。

4

2 回答 2

8

通常的方法是使用递归异步回调来处理每个单独的记录,而不是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();
    }
})();
于 2012-10-17T15:38:17.653 回答
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 的所有好处,没有任何麻烦。

如果上述解决方案对您不起作用,请告诉我。

祝你好运!

约翰...

于 2012-10-17T15:27:48.487 回答