1

所以我们有一个现有的、相当大的应用程序,它使用了一个同步的 JavaScript API。在这种情况下,Google Gears SQL。我们正在尝试为我们的客户演示可以让应用程序在不支持齿轮的平台(在本例中为 iOS)上运行,如果他们喜欢他们所看到的,我们将使用 HTML5 以正确的方式重做整个应用程序localStorage 但现在我们需要使用 Web SQL 让它工作,即使效果不佳。问题当然是 Web SQL 是异步的,而 Gears SQL 是同步的。我们已经有了一个用于与齿轮对话的抽象,因此如果我们想更改该抽象以与 Web SQL 对话。我尝试使用这样的方法:http: //jsfiddle.net/ZCD4u/伪造同步行为,但 Web SQL 查询在被阻止时从未执行。我还尝试将所有 db 内容放在 web worker 中,认为它会阻塞页面但无论如何都会执行 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);
};

sleep由于在Javascript中不是真实的东西而不起作用的解决方案:

var myCoolAbstraction = function(sql) {
    var res;
    doWebSQLThing(sql, function(d) {
        res = d;
    });
    while (res === undefined) {
        sleep(100);
    }
    return res
};

任何更改上述第一个代码块中代码的行为或内容的解决方案都会失败。

编辑:我怀疑这无法完成,我们正在研究此演示的其他选项,但我很想知道是否有人有解决方案。

4

1 回答 1

1

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 nightly 和 Chrome 上测试这个单元测试并打开和谐标志。

于 2013-11-05T01:42:19.830 回答