web-dev-qa-db-ja.com

条件が満たされるまで、JavaScript関数から戻るのを待ちます

これは奇妙な問題です。 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と組み合わせて使用​​しますが、これは機能しないと確信しています。

あなたの提案をいただければ幸いです。

10
findchris

コードを実行するにはafter非同期操作が成功したため、continue。これは、操作が完了したときにコードが呼び出す単なるコールバックにすることができます。

このようなもの:

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);
17
Jordão

非同期が終了するのを待つために、ループ(オプションでタイムアウト付き)を実行できます。警告、これは(要求に応じて)他のすべての機能をブロックし、時間がかかりすぎるとブラウザがフリーズする可能性があります。ただし、このようにブロックするのではなく、必要なことを実行する非同期の方法を実際に理解する必要があります。

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;
}
1
six8