Javascript 将异步api转换为同步api。(我有很好的理由保证)

Javascript 将异步api转换为同步api。(我有很好的理由保证),javascript,asynchronous,web-sql,google-gears,Javascript,Asynchronous,Web Sql,Google Gears,因此,我们有一个现有的相当大的应用程序,它使用的是同步javascript API。在本例中,GoogleGearsSQL。我们正在尝试向我们的客户演示,让应用程序在不支持gears的平台(在本例中为iOS)上运行是可能的,如果他们喜欢他们所看到的,我们将使用HTML5 localStorage以正确的方式重做整个应用程序,但目前我们需要使用Web SQL使其工作,即使效果很差。当然,问题是Web SQL是异步的,而Gears SQL是同步的。我们已经有了一个用于与gears对话的抽象,所以如果

因此,我们有一个现有的相当大的应用程序,它使用的是同步javascript API。在本例中,GoogleGearsSQL。我们正在尝试向我们的客户演示,让应用程序在不支持gears的平台(在本例中为iOS)上运行是可能的,如果他们喜欢他们所看到的,我们将使用HTML5 localStorage以正确的方式重做整个应用程序,但目前我们需要使用Web SQL使其工作,即使效果很差。当然,问题是Web SQL是异步的,而Gears SQL是同步的。我们已经有了一个用于与gears对话的抽象,所以如果我们想将该抽象改为与web SQL对话的话。我尝试使用这样一种方法:伪造同步行为,但Web SQL查询在被阻止时从未执行。我还试着将所有的db内容放在一个web工作者中,认为它会在页面中阻塞,但无论如何都会执行SQL。问题是,当我的睡眠循环仍然阻塞时,等待工作人员回复的侦听器从未被解雇。我需要的是一种修改使用同步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);
};
解决方案不起作用,因为
睡眠
在Javascript中不是一个真正的东西:

var myCoolAbstraction = function(sql) {
    var res;
    doWebSQLThing(sql, function(d) {
        res = d;
    });
    while (res === undefined) {
        sleep(100);
    }
    return res
};
任何更改上述第一个代码块中代码的行为或内容的解决方案都会失败


编辑:我怀疑这是不可能的,我们正在为这个演示寻找其他选项,但我想知道是否有人有解决方案。

WebSQL是异步API。无法将异步函数转换为同步函数,因为它依赖于从运行到完成的执行模型。这意味着回调函数只有在当前执行堆栈完成后才会调用

然而,新的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'));

您可以每晚在Firefox和打开harmony标志的Chrome上进行测试

WebSQL是异步API。无法将异步函数转换为同步函数,因为它依赖于从运行到完成的执行模型。这意味着回调函数只有在当前执行堆栈完成后才会调用

然而,新的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'));

您可以每晚在Firefox和打开harmony标志的Chrome上进行测试

我不确定它是否能直接满足您的需求,但几天前我偶然发现了jQuery BlockUI插件:可能与今天早上的版本相同,我会说这是不可能的。然后我被这个聪明但邪恶的黑客绊倒了。记住,伟大的力量带来伟大的责任。明智地使用它:@MikeEdwards这确实是一个了不起的黑客。有趣的是,这个特殊用例的全部要点是,我们需要它离线运行,这样这个黑客就不会为我们工作了。你可能运气不好。问题是JS是单线程的。当你调用一个异步API时,在解释器返回到主事件循环之前,它无法得到结果,而主事件循环是在你的函数返回之后。我不确定它是否直接满足了你的需要,但几天前我偶然发现了jQuery BlockUI插件:今天早上的可能重复我会说这是不可能的。然后我被这个聪明但邪恶的黑客绊倒了。记住,伟大的力量带来伟大的责任。明智地使用它:@MikeEdwards这确实是一个了不起的黑客。有趣的是,这个特殊用例的全部要点是,我们需要它离线运行,这样这个黑客就不会为我们工作了。你可能运气不好。问题是JS是单线程的。调用异步API时,只有解释器返回到主事件循环才能得到结果,而主事件循环是在函数返回之后。谢谢,不幸的是,这无法解决问题,因为我们需要它在不支持屈服的地方工作。谢谢,不幸的是,这无法解决问题,因为我们需要它在不支持产量的地方工作。