因此,我们有一个现有的、相当大的应用程序,它使用同步 javascript API。在本例中是 Google Gears SQL。我们正在尝试向客户演示,可以让应用程序在不支持 gears 的平台上运行(在本例中为 iOS),如果他们喜欢他们所看到的内容,我们将使用 HTML5 以正确的方式重做整个应用程序localStorage,但现在我们需要使用 Web SQL 让它工作,即使效果很差。当然,问题在于 Web SQL 是异步的,而 Gears SQL 是同步的。我们已经有了一个用于与 gears 对话的抽象,因此如果我们想更改该抽象以与 Web SQL 对话。我尝试使用这样的方法:http://jsfiddle.net/ZCD4u/伪造同步行为,但 Web SQL 查询在被阻止时从未执行。我还尝试将所有数据库内容放入 Web Worker 中,认为它会在页面中阻塞,但无论如何都会执行 SQL。问题是,当我的 sleep 循环仍然阻塞时,等待工作人员回复的监听器永远不会被解雇。我需要的是一种修改使用同步 api 的抽象的方法,以便它改为使用异步 api,而不更改我自己的抽象的 api。也就是说,如果当我完成抽象时,它向应用程序的其余部分公开回调机制,那么我就失败了。更具体地说:
我不允许更改的文件:
var sql = 'SELECT things FROM tables';
var res = myCoolAbstraction(sql);
dothings(res);
我需要更改的文件,以便它可以使用 Web SQL 而不是 Gears:
var myCoolAbstraction = function(sql) {
return doGearsThing(sql);
};
解决方案不起作用,因为 sleep
在 Javascript 中不是真实存在的:
var myCoolAbstraction = function(sql) {
var res;
doWebSQLThing(sql, function(d) {
res = d;
});
while (res === undefined) {
sleep(100);
}
return res
};
任何更改上述第一个代码块中代码的行为或内容的解决方案都会失败。
编辑:我怀疑这无法完成,我们正在研究此演示的其他选项,但我很想知道是否有人有解决方案。
最佳答案
WebSQL 是异步 API。无法将异步函数转换为同步函数,因为它依赖于运行到完成执行模型。这意味着回调函数只有在当前执行堆栈完成后才会调用。
但是有generator在新的 ecmascript 标准中,允许暂停执行上下文。执行在每个yield 语句上暂停。您可以使用该功能在数据库请求异步时编写线性工作流程,如下所示:
var db = new ydn.db.Storage(db_name, schema);
db.spawn(function* (tdb) {
var value_1 = yield tdb.get('st', key_1);
value_1.amount += 10;
var key_1 = yield tdb.put('st', value_1);
var value = yield tdb.get('st', key_1);
console.log(value);
};, ['st'], 'readwrite'));
您可以测试this unit test在 Firefox nightly 和 Chrome 上,并且启用了 Harmony 标志。
关于javascript - 将异步 api 转换为同步 api。 (我有充分的理由保证),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19779955/