如何在JavaScript中阻止异步函数

13

我需要在JavaScript中编写一个函数,该函数从调用异步函数返回状态。但是,调用者只接收值,并且不需要提供回调函数。我尝试了以下代码:

function getState() {
    var ret = null;
    asyncCall("request",
        function() { ret = "foo"; } // callback
    );
    while (ret === null)
        ; // block on the asynchronous call
    return ret;
}

然而,这个循环永远不会结束...

有什么想法吗?谢谢。


2
你为什么要阻止异步调用呢?这样做没有任何意义。 - Tomalak
4
因为这是Firefox提供的一个调用,我无法更改它。预计最多需要几毫秒,我不想为此重构我的其他代码。 - Ryan Li
你能发布调用 getState() 函数的代码吗? - Tomalak
@Tomolak:这个函数太长了,不适合在这里发布,而且预计会从很多地方调用。因此,我希望这个函数能够返回一个值。 - Ryan Li
你有没有得到任何关于这个问题的有效答案?我也遇到了同样的问题,到目前为止还没有找到合适的答案。现在我唯一的选择是在许多地方重构代码以与异步方法一起使用。 - keya
5个回答

9
我想你正在寻找 StratifiedJS,http://stratifiedjs.org 它可以让你像编写同步代码一样“指挥”异步代码,但请注意它不会阻塞应用程序的其他部分。你只需加载 apollo js 库即可在任何地方使用它。
以下是在 Stratified JavaScript 中的示例:
function getState() {
  waitfor (var ret) {
    // block on the asynchronous call
    asyncCall("request", resume);
  }
  return ret;
}

当然,也有一些模块/库可以让它看起来像这样:http://onilabs.com/modules#http
function getState() {
  return http.get("request");
}

虽然这依赖于一个外部解析器,但在这里似乎是最好的解决方案。 - Ryan Li
是的,但在整个方案中,它并不会增加太多开销。 - tomg

1
最好的方法是将您想要调用的逻辑放入回调函数中。有没有什么原因你不能这样做呢?
您可以使用 setInterval 来检查结果,但这也需要一个回调函数...

我正在编写一个扩展,而不是普通的文档JavaScript。函数的其余部分依赖于此状态,并且唯一提供的是一个异步函数。 - Ryan Li

1
为什么不直接:
asyncCall("request", function() {
    // here you can inspect the state
});

包装函数的作用是什么?

异步函数的工作方式是这样的。如果您想阻止执行,则使用同步调用:

var state = syncCall("request");

这有点像一个库,因为我要在多个平台上工作。而且其余的代码需要等待这个特殊的信息。没有提供同步替换。 - Ryan Li
2
@Šime:你的意思是异步调用可能会影响到调用它的所有其他代码吗?我只是想知道是否有一种方法可以阻止这些异步调用。 - Ryan Li
1
@ryanli:除非你A:将异步调用重写为同步调用,或者B:重写你的代码以在异步环境中工作,否则没有阻止异步调用的方法。自1999年以来,在JavaScript中,最佳实践是选择B。 - slebetman

1

除非我误解了你的问题,否则你可以查看jQuery的ajaxStop()事件 - http://api.jquery.com/ajaxstop。这会阻塞直到所有ajax调用完成。这显然要求所有异步调用都通过jQuery完成。

$(document).ajaxStop(function() {
    // do your "ajax dependent" stuff here
});

0

我知道这一点,但它不是XHR请求。 - Ryan Li

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接