将异步 API 转换为同步 API.(我保证有一个很好的理由)

converting an asynchronous api to synchronous one. (I have a good reason I promise)

本文关键字:API 有一个 很好 理由 转换 异步 同步      更新时间:2023-09-26

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

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

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

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

然而,在新的 ecmascript 标准中有一个生成器,它允许暂停执行上下文。执行在每个收益语句上暂停。您可以使用该功能在数据库请求异步时编写线性工作流,如下所示:

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