0

フラグがtrueになるまでJavaScriptの実行を一時停止するにはどうすればよいですか?

たとえば、次のようなxmlメッセージがあります。

[...]
<action>
    <resource update>id</resourceupdate>
</action>
<action>
    <event>id1</event>
</action>
<action>
    <event>id2</event>
</action>
<action>
    <event>id3</event>
</action>
[...]

イベントノードがノードresourceupdateの処理後にのみ処理されることを望みます(ページのロードが必要になるため、処理に時間がかかります)。

私が試したイテレータ(それぞれ)でこのメッセージを処理するためのjavascriptで:

$(_response).find('ACTION').each(function() {       
if (tagName=="RESOURCEUPDATE") {
    ready = false;
    //load the resource with selected id in an iframe
} else if (tagName=="EVENT") {
    browserLoaded();   //the waiting function
    eventhandler();  //consume the event
}
});

待機機能は次のとおりです。

function browserLoaded() {
if (!ready) {
    setTimeout(browserLoaded(),1000);
}
} 

iframeが読み込まれるとreadyvarがtrueになります。

$(iframe).load(function() {
    ready = true;
});

しかし、実行すると、このエラーが発生します。

 Maximum call stack size exceeded error

何か案は?ありがとう!

4

5 に答える 5

0

簡単なハックの1つは、ポーリングループを設定することです。setIntervalを使用して、変数が設定されているかどうかを時々チェックし、clearIntervalを使用して、その時点で実行を続行します。

とにかく、それは物事を行うのに苦痛になるでしょう。基本的に、Javascriptで何かを後者で実行するように指示する唯一の方法は、それを関数内にパッケージ化することです。ただし、これを実行すると、その関数を渡して、完了時に非同期コードにコールバックさせることができるため、簡単になります。

たとえば、処理は次のようになります。

//this is a simple "semaphore" pattern:
var things_to_load_count = 1
var check_if_done(){
    things_to_load_count--;
    if(things_to_load_count <= 0){
        //code to do stuff after you finish loading
    }
};

$(_response).find('ACTION').each(function() {
    if (tagName=="RESOURCEUPDATE") {
        things_to_load_count++;
        run_code_to_load_stuff( check_if_done )
        //make sure that the run_code_to_load_stuff function
        //calls the callback you passed it once its done.
    } else if (tagName=="EVENT") {
        //process one of the normal nodes
    }
});

//this will run the remaining code if we loaded everything
//but will do nothing if we are still waiting.
check_if_done()
于 2012-12-17T22:03:16.583 に答える
0

iframe ロード関数で true を設定する ready 変数が、別の settimeout が呼び出される前にチェックされる変数と同じであることを確認します。iframe ロード関数の 1 つがローカル変数で、もう 1 つがグローバル変数のようです。

または、ready 変数が両方ともローカルです。

于 2012-12-17T22:21:33.580 に答える
0

問題は、スタックがいっぱいになるまで自分自身を呼び出すこの関数にあります。

function browserLoaded() {
  if (!ready) {
    //here you call browserLoaded function instead of passing a reference to the function
    setTimeout(browserLoaded() ,1000);
  }
} 

関数は次のようになります。

function browserLoaded() {
  if (!ready) {
    // note the missing "()"
    setTimeout(browserLoaded, 1000);
  }
} 
于 2012-12-17T21:50:24.087 に答える
0

これはひどい設計です。「待機」タイムアウトメカニズムは必要ありません。jQuery ajax リクエストを介してページをロードしている場合は、コールバック関数を使用してコードの実行を続行します (おそらく、処理中の「現在の」アイテムを追跡して、次のアイテムを続行できます)。iFrame をロードしている場合、それも設計が悪いため、jQuery ajax の方法に移行する必要があります。

于 2012-12-17T21:52:32.457 に答える
0

ある種のフラグを使用するのは本当に悪い考えです。Deferred パターンを使用する必要があります。このようなもの:

var resources = [];
$(_response).find('ACTION').each(function() {
  var deferred = resources.length > 0 ? resources[resources.length - 1] : null;

  switch (tagName) {
    case "RESOURCEUPDATE":
      deferred = $.Deferred();

      //load the resource with selected id in an iframe
      $(iframe).bind('load', function () {
        deferred.resolve(/*specific arg1, arg2, arg3, ...*/)
      });
      resources.push(deferred);
      break;
    case "EVENT":       
      if (deferred) {
         deferred.done(function (/*specific arg1, arg2, arg3, ...*/) {
            // process event node
         });
      }
      break;
  }
});

// clean up deferreds objects when all them will be processed
$.when.apply($, resources).then(function() {
  resources.length = 0;
})

PS : http://api.jquery.com/category/deferred-object/

于 2012-12-17T22:12:09.780 に答える