同步查询Web SQL数据库
我正在研究一些与客户端 SQLite 数据库交互的 JavaScript,通过新的 window.openDatabase(...)
、database.transaction(...)< /code> 和相关 API。大多数人都知道,当您以这种方式执行查询时,它是一个异步调用,这通常是好的。您可以通过回调进行调用并根据需要处理结果。
在我目前的情况下,我正在为客户端开发一种算法,该算法在本地存储的数据库中执行一些层次结构行走。我遇到问题的算法部分需要从某行开始,该行引用了表中另一行的“父级”(通过 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 的浏览器上都没有看到任何迹象。
任何人都可以提供关于我如何可能的建议,a。使用回调正确地制定这些迭代的、相互依赖的查询,或者,b.以某种方式让调用以同步或明显同步的方式实际发生。
非常感谢任何尝试解决这个看似棘手的小问题的人。
奈姆
P.S.下面是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;
},
.
.
.
I'm working on a bit of JavaScript that interacts with a client-side SQLite database, via the newish window.openDatabase(...)
, database.transaction(...)
and related APIs. As most of you know when you execute a query in this way it is an asynchronous call, which is typically good. You can make the call and handle the results as appropriate with callbacks.
In my current situation I'm working on an algo for a client that does some hierarchy walking in the locally stored database. The part of the algo I'm having trouble with requires starting at some row, which has a reference to a "parent" (by id) that is another row further up in the table. I have to keep walking up this tree until I reach the root.
The problem is that I'm at a point where I'm not sure how to use an asynchronous style query with a callback to keep feeding the loop parent ids. Ideally I could get the query to block so that I can do it all in the loop. Here's the key parts of my current setup:
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;
}
}
As you might imagine, it doesn't work well. hierarchyArr gets an "undefined" pushed into it, and then the script crashes when it tries to check the type of rs[0].
When I try to set it up with a callback (db.getRSAndCallback(sql, callbackFunc)
, which I used for the earlier, non-interdependent queries just fine) it's worse: the inner loop takes off like crazy because id isn't getting updated; presumably because the loop is keeping the JavaScript interpreter so busy that it never actually fills rs
. In some artificial testing where I forced the inner loop to break after a few iterations all the callbacks started coming through all at the end, after the loop finished.
The "standard" (such as it is right now) at http://dev.w3.org/html5/webdatabase/#synchronous-database-api seems to indicate that there is a synchronous API, but I haven't seen any sign of it on any WebKit based browsers.
Can anyone offer suggestions on how I might either, a. properly formulate these iterative, interdependent queries using callbacks or, b. somehow get the call to actually happen in a synchronous or apparently synchronous manner.
Many thanks in advance for anyone who takes a crack at this seemingly tricky little problem.
Naim
P.S. Here's the client's implementation of db.getRS
for reference:
.
.
.
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;
},
.
.
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我使用回调和闭包来解决类似的问题,请考虑:
在此示例的延续中,文件夹有一个属性 parent 来定义它与其他文件夹的关系。就像文档一样。以下内容将使用闭包获取文档的路径(成功):
I used callbacks and a closure to solve a similar problem, consider:
In the continuation of this example, folder has a property parent to define it's relation to other folders. As does a document. The following will get you the path of a document using a closure (success):
您可以使用回调来关闭剩余查询堆栈。或者您可以使用递归,将堆栈作为参数传递。
You could use callbacks with a closure to your stack of remaining queries. Or you could use recursion, passing the stack as parameters.