【问题标题】:Populating a database table with returned JSON使用返回的 JSON 填充数据库表
【发布时间】:2013-07-10 20:20:36
【问题描述】:

我希望将一些 JSON 内容从 Drupal 网站存储到 PhoneGap 应用程序中的数据库表中。我正在使用 ajax 来执行此操作。当我运行以下代码并检查表时,我被告知它是空的。有人知道我如何填充这张表吗?

$('#newDiv').live('pageshow',function(){

    function queryDB(tx) {
        tx.executeSql("SELECT * FROM 'tableA'", [], querySuccess, errorCB);
    }

    function querySuccess(tx, results) {
        var len = results.rows.length;
        alert("Table: " + len + " rows were found.");
        }
    }

    function createTable(tx) {

        tx.executeSql('DROP TABLE IF EXISTS "tableA"');
        var sql = "CREATE TABLE IF NOT EXISTS 'tableA' (id INTEGER PRIMARY KEY AUTOINCREMENT, step VARCHAR(50), text VARCHAR(50))";
        tx.executeSql(sql, [], successCB, errorCB); 
    }

    db.transaction(createTable, errorCB, successCB);

   $.ajax({
        url: myURL,
        type: 'post',
        data: 'tid=4',
        dataType: 'json',
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            alert('new_page_node_view - failed to retrieve page node');
            console.log(JSON.stringify(XMLHttpRequest));
            console.log(JSON.stringify(textStatus));
            console.log(JSON.stringify(errorThrown));
        },     
        success: function (data) {

            $.each(data, function (node_index,node_value) {
               db.transaction(function(tx){
                       tx.executeSql("INSERT INTO 'tableA' (step, text) VALUES (?, ?)",[node_value.title, node_value.body]);
               });
            });
          }
      });

    db.transaction(queryDB, errorCB, successCB);


});

【问题讨论】:

  • 在等待 AJAX 完成之前,您正在运行 queryDB 事务。您应该在 success 回调中执行此操作。
  • @Barmar 这当然是一个问题。另一个问题是,当他调用 queryDB 时,并非所有插入都可以完成 - 我对脚本进行了编辑,该脚本将在所有插入完全完成后在适当的时间调用 queryDB。

标签: jquery ajax json jquery-mobile cordova


【解决方案1】:

嘿tipsch试试这个-

  var numInserts = 0;

  $.ajax({
        url: myURL,
        type: 'post',
        data: 'tid=4',
        dataType: 'json',
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            alert('new_page_node_view - failed to retrieve page node');
            console.log(JSON.stringify(XMLHttpRequest));
            console.log(JSON.stringify(textStatus));
            console.log(JSON.stringify(errorThrown));
        },     
        success: function (data) {
            numInserts = data.length; // num of inserts to expect (assumes data is in array of objects)

            $.each(data, function (node_index,node_value) {
               db.transaction(function(tx){
                       tx.executeSql("INSERT INTO 'tableA' (step, text) VALUES (?, ?)",[node_value.title, node_value.body],
                       function(tx, results){
                            numInserts--; // decrement 1 from expected num of inserts
                            if (numInserts == 0){
                                db.transaction(queryDB, errorCB, successCB);
                            }
                       }, 
                       function(tx, err){
                        console.log("insert error");
                        if (err){
                            console.log(err);
                        }
                       });
               });
            });
        }
  });

/Update - 回答为什么上述方法是必要的。

好的,所以您可能想知道为什么不直接在 $.each 循环之后的 AJAX 调用的成功回调中立即调用 queryDB,如下所示 -

   $.ajax({
        url: myURL,
        type: 'post',
        data: 'tid=4',
        dataType: 'json',
        error: function (XMLHttpRequest, textStatus, errorThrown) {
            alert('new_page_node_view - failed to retrieve page node');
            console.log(JSON.stringify(XMLHttpRequest));
            console.log(JSON.stringify(textStatus));
            console.log(JSON.stringify(errorThrown));
        },     
        success: function (data) {
            $.each(data, function (node_index,node_value) {
               db.transaction(function(tx){
                    tx.executeSql("INSERT INTO 'tableA' (step, text) VALUES (?, ?)",[node_value.title, node_value.body]);
               });
            });
            db.transaction(queryDB, errorCB, successCB); // <-- the inserts could not all be finished when this gets called
        }
   });

假设您要从 JSON 结果中插入 1000 条记录。当您在 AJAX 调用成功时调用 db.transaction(queryDB, errorCB, successCB); 时,这些插入不会完成。您必须对 tx.executeSql 插入执行成功回调,以了解插入何时完成。

我在上面的第一种方法中所做的将允许在您调用 queryDB 函数之前完全完成所有插入。我向tx.executeSql("INSERT INTO 'tableA' (step, text) VALUES (?, ?)",[node_value.title, node_value.body]); 添加了内联成功和失败回调。我总是建议对 PhoneGap 中的任何 WebSQL 执行此操作(它们也不必内联)。

在之前的工作中,我在 PhoneGap 中进行了大量的 WebSQL 事务。其中大部分涉及循环 JSON 并将其写入本地数据库表。当您有许多插入并试图在通知用户之前弄清楚它们何时全部完成时,或者在您的情况下将刚刚写入的数据拉出时,就会出现真正的困难问题。

所以...在插入的情况下,您将学习的技巧是 -

  1. 计算您期望执行的插入次数并将其存储在变量中。
  2. 在您的tx.executeSql insert 的成功回调中,从包含您期望的插入数量的变量中减去 1。
  3. 一旦变量在 tx.executeSql 成功回调中变为 0,那么您就知道您的所有插入都已完成。

1 个插入的简单示例 -

// wrong approach here
db.transaction(function(tx){
    tx.executeSql("INSERT INTO 'tableA' (step, text) VALUES (?, ?)",["foo", "bar"]);
    // it will start the select query before the insert has completed
    tx.executeSql("SELECT * FROM 'tableA'", [], querySuccess, errorCB);
});

// the right approach here
db.transaction(function(tx){
    tx.executeSql("INSERT INTO 'tableA' (step, text) VALUES (?, ?)",["foo", "bar"], insertDone, insertFail);
});

function insertDone(tx, results){
    // insert is done, now you can run the queryDB
    tx.executeSql("SELECT * FROM 'tableA'", [], querySuccess, errorCB);
}

function insertFail(tx, err){
    console.log("insert error");
    if (err){
        console.log(err);
    }
}

我希望这有助于澄清为什么我使用第一种方法而不是仅在 AJAX 调用的成功回调中运行 queryDB

希望这一切对未来的人有所帮助,哈哈。

【讨论】:

  • 成功了,感谢一百万罗斯。你介意解释一下为什么我自己的代码没有给我任何东西吗?
  • @tipssch Barmar 在上面指出您在等待 AJAX 完成之前调用了 queryDB 事务是正确的。但是,即使您在 AJAX 调用的 success 回调中调用了 queryDB,您的插入也可能尚未完成。这里的问题是,当您在 PhoneGap 中使用 WebSQL 时,它是异步的。我总是建议在您的tx.executeSql 中实现一个回调,该回调将在事务完成时触发(回调也不必是内联的)。我将编辑我的答案并说明更多内容。
  • 非常感谢,这非常有帮助!我真的很感激
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-27
  • 1970-01-01
  • 2015-04-04
  • 1970-01-01
  • 2016-12-08
  • 1970-01-01
相关资源
最近更新 更多