【问题标题】:Synchronous query to Web SQL Database对 Web SQL 数据库的同步查询
【发布时间】:2011-04-23 14:54:58
【问题描述】:

我正在开发一些 JavaScript,它通过新的 window.openDatabase(...)database.transaction(...) 和相关 API 与客户端 SQLite 数据库交互。大多数人都知道,当您以这种方式执行查询时,它是一个异步调用,这通常很好。您可以使用回调进行调用并根据需要处理结果。

在我目前的情况下,我正在为一个客户端开发一个算法,该算法在本地存储的数据库中执行一些层次结构。我遇到问题的算法部分需要从某行开始,该行引用了表中另一行的“父”(按 id)。我必须一直走上这棵树,直到我到达树根。

问题是我不确定如何使用带有回调的异步样式查询来继续提供循环父 ID。理想情况下,我可以阻止查询,以便我可以在循环中完成所有操作。这是我当前设置的关键部分:

    for (i in search.searchResults.resultsArray)
    {
        hierarchyArr = new Array();
        pageHierarchyArr = new Array();
        id = search.searchResults.resultsArray[i].ID;

        while (id != null && id != "")
        {
            var hierarchySql = "SELECT ID, parentID, type, content FROM content WHERE ID = " + id;

            // This is a prettied up call to database.transaction(...)
            var rs = db.getRS(hierarchySql);

            // Ideally the code below doesn't execute until rs is populated

            hierarchyArr.push(rs[0]);

            if (rs[0].type == "page")
            {
                pageHierarchyArr.push(rs[0]);

                // Do some additional work
            }

            id = rs[0].parentID;
        }
    }

正如您可能想象的那样,它运行不佳。 hierarchyArr 将“未定义”推入其中,然后脚本在尝试检查 rs[0] 的类型时崩溃。

当我尝试使用回调设置它时(db.getRSAndCallback(sql, callbackFunc),我在前面的非相互依赖查询中使用它就好了),更糟糕的是:内部循环像疯了一样起飞,因为 id 没有得到更新;大概是因为循环使 JavaScript 解释器如此忙碌,以至于它实际上从未填满rs。在一些人工测试中,我在几次迭代后强制内部循环中断,所有回调在循环结束后开始全部通过。

http://dev.w3.org/html5/webdatabase/#synchronous-database-api 的“标准”(例如现在的)似乎表明存在同步 API,但我在任何基于 WebKit 的浏览器上都没有看到任何迹象。

任何人都可以就我的方式提出建议吗?使用回调或 b. 正确地制定这些迭代的、相互依赖的查询。以某种方式让调用以同步或明显同步的方式实际发生。

非常感谢任何解决这个看似棘手的小问题的人。

奈姆

附:下面是客户端对db.getRS的实现供参考:

.
.
.
getRS: function(sql)
{
    var output = [];
    db.database.transaction(function(tx)
    {
        tx.executeSql(sql, [], function(tx,rs)
        {
            for(i = 0; i < rs.rows.length; i++)
            {
                output.push(rs.rows.item(i));
            }
        },
        function(tx, error) { ... }
    )});
    return output;
},
.
.
.

【问题讨论】:

  • 哦,我还想提一下:如果我正在调试脚本并且我在hierarchyArr.push(rs[0]); 上设置了一个断点,那么脚本就可以正常工作。遍历它,记录集被填充,id 被更新,它遍历层次结构。禁用断点并让它运行并在我上面提到的地方崩溃,毫无疑问是因为当前执行的暂停让它完成了查询。

标签: javascript sqlite synchronization web-sql


【解决方案1】:

我使用回调和闭包来解决类似的问题,请考虑:

function getFolder(id, callback) {
var data = [];
ldb.transaction(function (tx) {
tx.executeSql('SELECT * FROM folders where id=?',
    [id],
    function (tx, results) {
        if (results.rows && results.rows.length) {
            for (i = 0; i < results.rows.length; i++) {
                data.push(results.rows.item(i));
            }
        }
        if (typeof(callback) == 'function')
            callback(data);
    },
    function (tx, error) {
        console.log(error);
    });
});
}

在此示例的后续部分中,文件夹有一个属性 parent 来定义它与其他文件夹的关系。和文件一样。以下将为您提供使用闭包的文档路径(成功):

  function getDocPath(doc, callback) {
      var path = [];
      var parent = doc.parent;
      var success = function(folder) {
         var folder = folder[0];
         parent = folder.parent;
         path.push({'id':folder.id,'name':folder.name});
         if (parent != "undefined")
             getFolder(parent, success);
         else
             if ( typeof(callback) == 'function' ) callback(path.reverse());
      }
      getFolder(parent, success);
  }

【讨论】:

  • 这就是我最终实现它的方式。感谢您花时间将您的代码放在这里供其他人使用!我忘了这样做。 :)
  • 对不起,请您解释一下将 data[] 变量放在外部作用域和回调函数中是否有任何区别?
【解决方案2】:

您可以对剩余查询堆栈使用带有闭包的回调。或者您可以使用递归,将堆栈作为参数传递。

【讨论】:

  • 是的,这些都是不错的选择。我认为递归可能是在这种情况下要走的路,但想坚持其他想法。幸运的是,我对完整数据集的处理不是记录之间相互依赖的,所以不会太混乱。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-24
  • 1970-01-01
相关资源
最近更新 更多