等待从javascript函数返回直到满足条件

时间:2011-12-01 03:25:24

标签: javascript asynchronous closures

这是一个奇怪的问题。我有一个客户端对象,我正在使用Crockford式的公共/私人成员构建:

var client = function() {
  var that, remote_data, other_data; 

  // add public interface
  that.doStuff = function(){...}

  // wait for remote resources to load
  remote_data = jsonRequest1();
  other_data  = jsonRequest2();

  return that;
};

我遇到的问题是我需要在返回新的'that'对象(它指示就绪客户端)之前加载一些远程JSON资源。数据以异步方式返回(显然),我设置布尔变量来指示每个远程资源何时返回。

我考虑过做类似以下的事情:

return whenInitialized(function() { return that; });

whenInitialized函数返回两个布尔标志是否为真。我将它与setInterval的组合一起使用,但我确信这不起作用。

非常感谢您的建议。

2 个答案:

答案 0 :(得分:17)

为了在异步操作成功后运行代码,您需要 continuation 。它可以只是代码在操作完成时调用的回调。

这样的事情:

var client = function(done) { // done is the callback
  var that, remote_data, other_data; 

  // add public interface
  that.doStuff = function(){...}

  // wait for remote resources to load
  var done1 = false, done2 = false;
  var complete1 = function() { done1 = true; if (done2) done(); };
  var complete2 = function() { done2 = true; if (done1) done(); };
  remote_data = jsonRequest1(complete1);
  other_data  = jsonRequest2(complete2);

  return that;
};

但是这些控制标志真的很烦人,并没有真正扩展。更好的,声明性的方法是使用jQuery deferreds

之类的东西
$.when(jsonRequest1(), jsonRequest2()).then(done);

答案 1 :(得分:2)

您可以执行循环(可选择使用超时)以等待异步完成。警告,这将(根据要求)阻止所有其他功能,并可能导致浏览器冻结,如果它需要太长时间。但是,你真的应该找到一种异步方式来做你需要的而不是像这样阻塞。

var syncRequest = function(options) {
    var is_finished = false;
    var result;
    var finished_callback = function(response) {
        is_finished = true;
        result = response.result;
    }

    ajax_request(options, finished_callback);

    // timeout in 30 seconds
    var timeout = (new Date()).getTime() + 30000;
    while ( !is_finished ) {
        if ( (new Date()).getTime() >= timeout ) {
            alert('Request timed out');
        }

        // do nothing, just block and wait for the request to finish
    }

    return result;
}