2

XMLHttpResponse オブジェクトを使用して、コメット スタイルのロング ポーリング接続を実装しようとしています。アイデアは、データが利用可能になったときにデータを送信するサーバーへのオープン接続を維持することです (偽のプッシュ)。XHR オブジェクトが完了するとすぐに、新しいデータを待機するために新しいオブジェクトを生成する必要があります。

以下は、機能するソリューションの概要を示すコードのスニペットですが、コメントが言うように、取り除く必要があるタイムアウトのためだけです。

window.onload = function(){
    XHR.init();
}


XHR = {
    init: function() {
        this.xhr = new XMLHttpRequest();
        this.xhr.open( "GET", "proxy.php?salt="+Math.round( Math.random()*10000 ), true );
        this.xhr.onreadystatechange = this.process.bind( this );
        this.xhr.send( null );
    },
    process: function() {
        if( this.xhr.readyState == 4 ) {

            // firebug console
            console.log( this.xhr.responseText );

            // ** Attempting to create new XMLHttpRequest object to
            // replace the one that's just completed
            // doesn't work without the timeout
            setTimeout( function() { this.init() }.bind( this ), 1000 );
        }
    }
}


Function.prototype.bind = function( obj ) {
    var method = this;
    return function() {
        return method.apply( obj, arguments );
    }
}


// proxy.php - a dummy that keeps the XHR object waiting for a response
<?php
$rand = mt_rand( 1, 10 );
sleep( $rand );
echo date( 'H:i:s' ).' - '.$rand;

問題は、ここの場合のように、オブジェクト (xhr) をそれ自体のイベント ハンドラー (プロセス) から削除できないことだと思います。特に、ハンドラー内の「this」は、削除しようとしているオブジェクト (xhr) を含むオブジェクト (XHR) にバインドされているためです。なんか円形!

誰でも助けることができますか?上記の例は、私が得ることができる最も近いものです。

4

7 に答える 7

1

jquery を使用して、次のようにします。

  function getData() {
    $.getJSON(someUrl, gotData);
  }

  // Whenever a query stops, start a new one.
  $(document).ajaxStop(getData, 0);
  // Start the first query.
  getData();

私のsloshの例ではこれを行います (ほとんどコメット サーバーであるため)。

于 2008-12-28T03:19:01.490 に答える
0

abort()メソッドを追加して、再利用を実装する方が簡単な場合があります。

XHR = {
    init: function() {
        if (!this.xhr) { // setup only once
            this.xhr = new XMLHttpRequest();
            this.xhr.onreadystatechange = this.process.bind( this );
        }
        this.xhr.abort(); // reset xhr
        this.xhr.open(/*...*/);
        this.xhr.send(null);
    },
    process: function() {
        if( this.xhr.readyState == 4 ) {

            // firebug console
            console.log( this.xhr.responseText );

            // start next round
            this.init();
        }
    }
};

@meouw[コメント]

同じ結果が得られる場合は、キャッシュの問題がある(Math.random()解決していない)か、以前のリクエストで送信されたものをマークしていない(毎回同じデータを再送信する)と思います。

于 2008-12-28T01:31:57.633 に答える
0

おそらく、これには XMLHTTPRequest をまったく使用しないでください。

数年前、XMLHTTPRequest が知られるずっと前に、私は通常のブラウザで使用するチャット プログラムを作成しました。チャットのあるウィンドウは、データが決して終わらない CGI スクリプトから来るフレームにありました。新しいデータがあるたびに送信するだけで、すぐにクライアントに表示されました。

今日は似たようなものを使用できると思います:

  • 更新を行う関数をページに作成します。
  • IFRAME を作成します。必要に応じて非表示にすることができます
  • IFRAME のソースを、データを生成するスクリプトに設定します
  • データは SCRIPT タグでカプセル化できます。私の記憶が正しければ、ブラウザは評価を試みる前に script タグの内容全体を取得する必要があります。更新関数を呼び出します。

    <script type="text/javascript">myupdate("mydata");</script> 
    
  • 送信するものがなくても、ブラウザでタイムアウトをリセットするために、5 秒ごとにスペースを送信してください。
  • 私の記憶が正しければ、ブラウザのプリフェッチ バッファを満たすために、トランザクションの開始時に約 1K のデータを送信する必要がありました (現在のブラウザでは、これを増やす必要があるかもしれません)。
于 2008-12-28T00:02:49.840 に答える
0

あなたがしているのは効果的なポーリングです。なぜ必要以上に複雑にして、数秒ごとにポーリングするのでしょうか? または、毎秒、実際にどれだけの時間を節約しているか、それは本当に重要であり、多くのユーザーがいる場合、サーバー側で非常に多くのソケットを占有することになります.

于 2008-12-27T22:26:46.383 に答える
0

しかし、実際にあなたの質問に答えてみるには、これではないものを削除する方法は、削除を行う関数を呼び出すようにタイマーを設定することです。その方法では、削除されているのはそれ自体ではありません。

于 2008-12-27T22:27:58.270 に答える
0

@stu

このアプリでは、応答時間が重要です。実際に重要なのは、すべてのクライアントが同時に (または可能な限り近くで) 更新されることです。

接続数は最大 50 までにかなり制限され、変更の間隔は数分になる可能性があります。

ポーリングを使用する場合、100ms までの非常に短い必要があります。これにより、非常に多くの不要なリクエストが発生します (これは、私がまとめた小さな php ソケット サーバーにとっては高価になります。サーバーですが、私はそれを十分に知りません)

于 2008-12-27T22:47:24.503 に答える