19

我正在使用 JavaScript API,其中大多数功能都是异步的。API 是WebKit JavaScript 数据库 API,它绑定到操作 SQLite3 数据库的功能子集。我理解使事物异步的设计决策,以不阻塞并提供响应式用户界面。在我的情况下,我知道我对异步 API 调用的使用将执行得很快。既然是这种情况,我想为我的开发人员提供一个更简洁、更易于使用的包装 API,它强制同步调用。

这是异步调用

db.executeSql(sqlStatement, function(result) {
  // do something with result
});

这就是我想做的

var result = dbWrapper.executeSql(sqlStatement);
// do something with result

有没有设计模式/方法可以做到这一点?首选编写或链接到代码示例。目标平台/浏览器是 iPhone 上的 Mobile Safari。

谢谢

4

7 回答 7

10

抱歉,JavaScript 不提供语言原语(例如线程或协程)来使异步事物同步运行,反之亦然。

您通常*仅获得一个执行线程,因此在导致创建请求的调用堆栈完全解开之前,您无法从计时器或 XMLHttpRequest readystatechange 获得回调。

所以简而言之,你不能真正做到;在您链接的 WebKit 页面上使用嵌套闭包的方法是我所知道的在这种情况下使代码可读的唯一方法。

*:除非在一些对您没有帮助并且通常被认为是错误的晦涩情况下

于 2008-10-18T12:31:04.687 回答
8

StratifiedJS 允许您这样做。

甚至还有一篇关于如何将其应用于浏览器存储的文章:http: //onilabs.com/blog/stratifying-asynchronous-storage

这是它使用的 Stratified JavaScript 库https://gist.github.com/613526

示例如下:

var db = require("webdatabase").openDatabase("CandyDB", ...);
try {
  var kids = db.executeSql("SELECT * FROM kids").rows;
  db.executeSql("INSERT INTO kids (name) VALUES (:name);", [kids[0]]);
  alert("done");
} catch(e) {
  alert("something went wrong");
}

也许有点晚了,但当时技术还不存在;)

于 2011-01-13T15:06:53.353 回答
4

您可以尝试以下方法:

function synch()
{
    var done = false;
    var returnVal = undefined;

    // asynch takes a callback method
    // that is called when done
    asynch(function(data) {
        returnVal = data;
        done = true;
    });

    while (done == false) {};
    return returnVal;
}

但这可能会在异步方法期间冻结您的浏览器......

或者看看 Narrative JavaScript:Narrative JavaScript 是 JavaScript 语言的一个小扩展,它支持异步事件回调的阻塞功能。这使得异步代码具有令人耳目一新的可读性和可理解性。

http://neilmix.com/narrativejs/doc/index.html

麦克风

于 2010-01-05T03:45:59.690 回答
1

我们正在使用 GWT RPC,它也有一个异步 API。我们目前用于串行进行多个异步调用的解决方案是调用链:

callA(function(resultA) {
    callB(resultA, function(resultB) {
        callC(); //etc.
    });
});

这种嵌套方法可以实现您想要的,但是对于新手来说它很冗长且难以阅读。我们研究的一种方法是将我们需要进行的调用添加到堆栈并按顺序执行它们:

callStack = [
    callA(),
    callB(),
    callC()
];

callStack.execute();

然后调用堆栈将管理:

  1. 串行调用调用(即第一个示例中的接线)
  2. 将结果从一个呼叫转发到下一个。

然而,由于 Java 没有函数引用,调用堆栈上的每个调用都需要一个匿名类,所以我们没有这样的解决方案。但是,您可能会在 javascript 中取得更大的成功。

祝你好运!

于 2008-10-18T12:26:33.853 回答
1

如果您使用的是 jQuery Ajax:$.ajax()

您可以将 asynch 的属性设置为 false ,然后您将向服务器发出同步 ajax 请求。

于 2008-10-18T11:30:31.800 回答
0

我不确定这是否是正确的地方,但我来到这里寻找在 Firefox 中进行同步调用的答案。解决方案是删除 onreadystatechange 回调并直接调用。这就是我发现的,我的解决方案 与休息服务同步回调

于 2011-01-26T19:04:35.797 回答
0

这实际上并没有实现数据库查询的同步操作,但这是我的易于管理的解决方案。基本上使用调用函数作为回调函数,并测试结果参数。如果函数接收到结果,它会解析它们,如果没有,它会将自己作为回调发送到查询方法。

 render: function(queryResults){
  if (typeof queryResults != 'undefined'){
   console.log('Query completed!');
   //do what you will with the results (check for query errors here)

  } else {
   console.log('Beginning query...');
   this.db.read(this.render); //db.read is my wrapper method for the sql db, and I'm sending this render method as the callback.
  }
 }
于 2011-01-10T00:33:47.250 回答