私は「奇妙な」方法でやっている場合、私は主に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にはシグナリングプリミティブがありません。
最初の方法が「うまくいかなかった」理由は、単にブラウザの再描画アルゴリズムの機能に過ぎません。シングルスレッド同期jsがブロックされているので、スレッドが処理している限り、ブラウザは再描画しません。しかし、アラートボックスがポップアップすると(コードは同期しており、ある意味ではブロックされていますが、フードの下では、再描画アルゴリズムに関する限り待機中/非ブロック状態を持っていると思います)おそらくアラートでうまくいっていたようだ。ちょうど実装のニュアンス。 – davin
しかし、同期jsコードは既に非同期のjsスレッドから呼び出されていました.. –
それは問題ではありませんが、私はあなたがそれがなぜ起こると思いますか分かりません。 "非同期スレッド"には意味がありません。コードの一部がイベントループに再入力されると、それは他のコードと区別できないため、実行が同期して開始されたかどうかに関係なく、現在の実行は同期しています。歩いている人もいれば、車で来る人もいれば(同期と非同期の間で、最もよく似ているとは限りませんが)、到着したらセキュリティで1つずつチェックされます。 – davin