繁体   English   中英

用于包装异步JavaScript函数以使其同步的模式

[英]Pattern for wrapping an Asynchronous JavaScript function to make it synchronous

我正在使用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

是否有设计模式/方式来做到这一点? 编写或链接到代码示例是首选。 目标平台/ broswer是iPhone上的Mobile Safari。

谢谢

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

您通常只获得一个执行线程,因此您不能从计时器或XMLHttpRequest readystatechange获得回调,直到导致创建请求的一堆调用完全解开。

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

*:除了在一些不起作用的模糊情况下,通常被认为是错误

StratifiedJS允许你做到这一点。

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

这是它使用的分层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");
}

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

您可以尝试以下方式:

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

麦克风

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

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

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

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

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

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

callStack.execute();

然后callstack会管理:

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

但是,因为Java没有函数引用,所以调用堆栈上的每次调用都需要一个匿名类,所以我们没有达到这样的解决方案。 但是,您可能在javascript中取得更多成功。

祝好运!

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

 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.
  }
 }

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM