2012-03-28 7 views
1

私は「奇妙な」方法でやっている場合、私は主にCの開発者であり、このAJAXの問題を私の場合と同様に解決しているC.JavaScript同期AjaxリクエストIdiosyncrasies

私は、メッセージが利用可能になるまで待ってから、その1つのメッセージだけを送信して接続を切断する「プッシュサーバー」に接続するスクリプトを持っています。クライアントは、将来のメッセージを待機するために接続を再確立する必要があります。

私は非同期コールバック内同期 AJAX呼び出しを実装することによって、これを実行しようとしました、そして、DOM(多分?私はここにJSの自分の無知を示​​していますが)全てまでブロックされます表示されます除いて、それが動作しますコールが完了しました。

私はコールバックを毎回コールバックすることによってスタックを使い果たしたくないので、純粋に非同期コールで行う方法はわかりません。

 $.ajax({ 
      url: './recoverDevice', 
      data: JSON.stringify(requestData), 
      dataType: 'json', 
      type: 'POST', 
      success: function(j) 
      { 
       console.log(j); 
       if (j.success) 
       { 
        //Indefinitely listen for push messages from the server 

        var loopMore = true; 
        while(loopMore) 
        { 
         $.ajax({ 
          async: false, 
          url: './getPendingMessage', 
          dataType: 'json', 
          type: 'POST', 
          success: function(j) 
          { 
           //alert(j.message); 
           $("#progressBox").append("<li>" + j.message + "</li>"); 
           loopMore = !j.complete; 
          } 
         }); 
        } 

       } 
       else 
       { 
        $("#errorBox").show(); 
        $("#errorBox").text(j.errorMessage); 
       } 
      } 
     }); 

さて、論理的に、このコードはず作品:

この

はコードです。 の非同期関数内では、私は 同期 JSコールをループします。メッセージを受け取るたびに、それをDOMに追加します。そして、サーバがメッセージを出さなくなったら、ループを終了します。非同期スレッドを終了してタスクを完了します。

問題は、DOMアクセスがすべてすべてのメッセージを受信した時点で合併しているように見えることです。すなわち、付加は、すべてのメッセージが受信され、非同期スレッドが終了したときにのみ起こる。

コメントアウトされたalertはテストでした。完全にです。それぞれの通知の後にメッセージボックスが表示され、次のメッセージまで(コードの残りの部分はそのまま)、正しく停止します。

これは私のブラウザ(Chrome)が、非同期スレッドが終了するまでDOM操作を許可しないことで競合状態から保護するための魔法をやっていると思いますか?または私はマークから離れてここに間違った木を吠えているのですか?

ループを削除してasyncをtrueに設定すると、最初のメッセージが正常に受信されます(問題はありません)が、それ以降はメッセージは表示されません。

function GetMessage() 
{ 
    $.ajax({ 
     async: true, 
     url: './getPendingMessage', 
     dataType: 'json', 
     type: 'POST', 
     success: function(j) 
     { 
      $("#progressBox").append("<li>" + j.message + "</li>"); 
      if (!j.complete) 
      { 
       GetMessage(); 
      } 
     } 
    }); 
} 

をしかし、それは時間をかけて(なし?)、スタックオーバーフローにつながる:

もちろん、私はこのような何かを行うことができます。

明白な解決策はここでも非同期呼び出しを使用することですが、whileループに一時停止して何らかの同期プリミティブを介して新しい呼び出しを続行するよう通知するのですが、JSにはシグナリングプリミティブがありません。

答えて

0

私はこれを前に見なかったのは分かりませんが、後者のコード断片は完全に機能します。私は投稿時にそれを認識しませんでしたが、スタックをオーバーフローさせることはできません。なぜなら、実行するたびに非同期呼び出しを出して終了するからです。スタックフレームは決して2〜3深くありません。非同期呼び出しは外部から管理され、スタック上には存在しないため、開始するたびに呼び出されます。

私はまだ最初のメソッド(非同期呼び出しの同期コード)が動作しなかった理由について、何か入力していただきありがとうございます。

+0

最初の方法が「うまくいかなかった」理由は、単にブラウザの再描画アルゴリズムの機能に過ぎません。シングルスレッド同期jsがブロックされているので、スレッドが処理している限り、ブラウザは再描画しません。しかし、アラートボックスがポップアップすると(コードは同期しており、ある意味ではブロックされていますが、フードの下では、再描画アルゴリズムに関する限り待機中/非ブロック状態を持っていると思います)おそらくアラートでうまくいっていたようだ。ちょうど実装のニュアンス。 – davin

+0

しかし、同期jsコードは既に非同期のjsスレッドから呼び出されていました.. –

+1

それは問題ではありませんが、私はあなたがそれがなぜ起こると思いますか分かりません。 "非同期スレッド"には意味がありません。コードの一部がイベントループに再入力されると、それは他のコードと区別できないため、実行が同期して開始されたかどうかに関係なく、現在の実行は同期しています。歩いている人もいれば、車で来る人もいれば(同期と非同期の間で、最もよく似ているとは限りませんが)、到着したらセキュリティで1つずつチェックされます。 – davin

関連する問題