0

XMLHttpRequestを使用してデータのリクエストをサーバーに送信するワーカースレッドがあります。その要求は、基本的にクライアントが持っている情報の現在の整合性をチェックするphpファイルを指し、クライアントが新しい情報を必要とする場合、それが送信されます。それ以外の場合、サーバーはクライアントが応答を必要とするまで情報をチェックします。サーバーが応答した後、プロセス全体が繰り返されます。

この問題は、スクリプトが応答していないことをブラウザが認識し、ユーザーにスクリプトを停止するオプションを提供した場合に発生します。ご覧のとおり、これは意図した結果ではありません。では、ブラウザを混乱させることなく、彗星のような構造を使い続けるための最良の方法は何でしょうか?

編集:スクリプトがハングしている理由を理解しました。スレッド内のどこかで繰り返すのではなく、ワーカースレッド全体を繰り返しました。ですから、私の質問は、プロセスが終了した後、どこからプロセスを再開するかということです。

<?php
//Client sends their current id

if(isset($_GET['id']))
    $id = $_GET["id"];

//if id doesnt match servers id send them a new one
//other wise do not respond

$server_id = file_get_contents("ids.txt");

while($server_id == $id){
    $server_id = file_get_contents("ids.txt");
    sleep(1);
}
echo $server_id;
?>

Javascript:

self.addEventListener('message', function(e) {
var data = e.data;
switch (data.cmd) {
    case 'start':
  getInfo(data.id);
  self.postMessage('ID :: ' + response);

  break;
default:
  self.postMessage('Unknown command');
};
}, false);


var response = null;
var request = new XMLHttpRequest();

function getInfo(inputID){
    var url = "serverResponse.php?id=" + inputID;
    request.open("GET", url, false);
    request.onreadystatechange = updateState;
    request.send(null);
}

function updateState(){
    if(request.readyState == 4){
        if(request.status == 200){
            response = request.responseText;//getInfo(data.id);
        }
    }
}    

html:

<html>

<script type="text/javascript">

function sayHI() {
    var id = "666";
    worker.postMessage({'cmd': 'start', 'id' : id});
  }

var worker = new Worker('AjaxWorker.js');
worker.addEventListener('message', function(e){
    document.getElementById('result').textContent = e.data;
    //Some data has been received so go ahead and make another call to the server
    //This is where the script hangs because the worker waits for a response
    sayHI();
}, false);


</script>


<body>
<button type="button" name="submit" id="submit" onclick="sayHI()">Submit</button>        </br></br>
<output id="result" name="result">Result</output>

</body>


</html>
4

2 に答える 2

1

あなたのライン:

request.open("GET", url, false);

async引数はにopen()設定されfalseています。これは、JavaScriptの実行フローが完了するまでそのAjax呼び出しで完全に停止することを意味します。その同期呼び出しが解決されるまで、Webページは完全にフリーズされます。また、長いポーリングを使用しているため、それは非常に長い間発生しません。したがって、ブラウザのインタプリタは、スクリプトの実行に疑わしいほど長い時間がかかっているという警告を送信します。(この警告も完全に正当です。同期呼び出しが解決されるまで、ページ上で何もできません。)

を使用する必要がありますrequest.open("GET", url, true);。Ajax呼び出しの後に発生する必要があるものをすべて移動し、onreadystatechangeコールバック内に配置するだけです。サーバーが最終的に応答すると、updateState関数が起動します。「cometpush」(つまり、サーバーからの応答によるロングポールクエリの解決)に応答して発生する必要があるものはすべて、そのコールバックに入る必要があります。

非同期Ajaxを使用すると、スクリプトの実行を続行でき、JSインタープリターがハングすることはありません。長いポーリングクエリが解決されるのを待つ代わりに、スクリプトフローはそのクエリを通過し、後でonreadystatechangeサーバーからの新しい情報を使用してコールバックが呼び出されます。

編集:

JavaScriptインタープリターにはスレッドが1つしかありません。そのスレッドが長期間ノンストップで使用されている場合、ブラウザは何かが間違っていると疑って警告を発します。同期Ajax呼び出しは、単一のJSスレッドを取得し、サーバーが最終的に応答するまで解放されません。前に言ったように、その長い間、ページ上で他に何も起こり得ません。通訳はその呼び出しで立ち往生しています。

同期Ajaxを使用すると、フローは次のようになります。

send synchronous request
wait
and wait
and wait
(meanwhile, nothing else can get done)
and wait...
....
finally a response comes!
use the response to update the page

この優れた非同期Ajaxの代替案を検討してください。

send ansyc request

[the interpreter sleeps and the browser is happy]

a response comes!
the request's readystatechange event fires now
the onreadystatechange handler uses the response to update the page

2番目の例では、インタープリターはAjaxリクエストが解決するのを待つ代わりに休憩を取ります。ハンドラーonreadystatechange関数は、Ajax呼び出しがサーバーから返されるたびに起動されます。呼び出しが同期している場合、インタプリタは呼び出しが解決するまで何もしません。onreadystatechange呼び出しが非同期の場合、インタプリタは、呼び出しが解決されてハンドラーが実行されるまで、休憩を含め、ブラウザーの警告を発生させないなど、好きなことを自由に行うことができます。

于 2012-07-11T17:20:06.757 に答える
0

リバースAJAX(HTTPポーリング?HTTPストリーミング?WebSocket?他の何か?)を実装するためにどの手法を使用しているのかはわかりません。ポーリングを使用している場合、サーバーは「ここでは何も新しいことはありません」としても迅速に応答するはずです。 。

接続を開いたままにしている場合、これにより問題が発生する可能性があります。HTTPは、ブラウザをサーバーへの2つの同時接続に制限します。その場合、ブラウザとその他のスクリプトには1つの接続しかありません。これにより、ブラウザは物事がブロックされていると見なす可能性があります。これに対する標準的なアプローチは、彗星の相互作用のために別のホスト名を作成することです。

WebWorkerを使用している場合、ブラウザーはWebWorkerがブロックされていることについて文句を言うことはありません。(ただし、接続数の問題は依然として問題を引き起こす可能性があります。)

于 2012-07-11T16:56:02.457 に答える