5

私は、サーバーからクライアントに多かれ少なかれ一定の更新を送信するために(jQueryのajax機能を介して)長いポーリングを使用するWebアプリ( Firefox互換のみ)を書いています。これを長時間、たとえば1日中または一晩実行したままにしておくことの影響が心配です。基本的なコードスケルトンは次のとおりです。

function processResults(xml)
{
    // do stuff with the xml from the server
}

function fetch()
{
    setTimeout(function ()
    {
        $.ajax({
            type: 'GET',
            url: 'foo/bar/baz',
            dataType: 'xml',
            success: function (xml)
            {
                processResults(xml);
                fetch();
            },
            error: function (xhr, type, exception)
            {
                if (xhr.status === 0)
                {
                console.log('XMLHttpRequest cancelled');
                }
                else
                {
                    console.debug(xhr);
                    fetch();
                }
            }
        });
    }, 500);
}

(0.5秒間の「スリープ」とは、更新がクライアントにすぐに返される場合に、クライアントがサーバーを攻撃しないようにするためです。通常はそうです。)

これを一晩実行したままにすると、Firefoxがクロールする傾向があります。基本的に無限再帰関数を作成したので、これはスタックの深さが大きいことが原因の一部である可能性があると考えていました。ただし、Firebugを使用してブレークポイントをにスローするとfetch、そうではないように見えます。Firebugが表示するスタックは、1時間後でも、約4または5フレームの深さしかありません。

私が検討している解決策の1つは、再帰関数を反復関数に変更することですが、スピンせずにAjaxリクエストの間に遅延を挿入する方法がわかりません。JS 1.7の「yield」キーワードを見てきましたが、ここで必要なものかどうかを判断するために、頭を完全に包むことはできません。

ページを定期的に、たとえば1時間に1回ハードリフレッシュするのが最善の解決策ですか?8時間または12時間実行した後でも、ブラウザに害を及ぼさない、より優れた/よりスリムなロングポーリングデザインパターンはありますか?または、サーバーが応答する頻度を通常知っているので、長いポーリングを完全にスキップして、別の「一定の更新」パターンを使用する必要がありますか?

4

4 に答える 4

2

からメモリがリークしているのではないかと思いますprocessResults()

私は長いポーリングのWebアプリケーションであなたのコードと非常によく似たコードを使用してきました。このアプリケーションは、ページを更新しなくても何週間も中断することなく実行できます。

fetch()すぐに戻るので、スタックを深くしないでください。無限に再帰的なループはありません。

Firefox Leak Monitorアドオンを使用して、メモリリークを見つけるのに役立てることができます。

于 2010-01-19T16:08:03.430 に答える
2

FireBug の可能性もあります。あなたは console.logging のものです。これは、おそらくネットワークモニタータブが開いていることを意味します。これは、すべてのリクエストがメモリに保存されていることを意味します。

無効にしてみて、それが役立つかどうかを確認してください。

于 2010-04-01T04:08:32.943 に答える
1

fetch()メソッド自体の内部から呼び出すのは悪い考えです。ある時点でメソッドが終了し、結果が呼び出し元に送信され始めると予想される場合は、再帰性を使用することをお勧めします。問題は、メソッドを再帰的に呼び出すと、呼び出し元のメソッドを開いたままにしてメモリを使用することです。深さが 3 ~ 4 フレームしかない場合は、jQuery またはブラウザーが何らかの形で「修正」しているためです。

jquery の最近のリリースでは、デフォルトでロング ポーリングがサポートされています。このようにして、無限再帰呼び出しを処理するためにブラウザーのインテリジェンスに依存していないことを確認できます。メソッドを呼び出すときに$.ajax()、次のコードを使用して長いポーリングを実行し、新しい呼び出しの前に 500 ミリ秒の安全な待機を組み合わせることができます。

function myLongPoll(){
    setTimeout(function(){
        $.ajax({
            type:'POST',
            dataType: 'JSON',
            url: 'http://my.domain.com/action',
            data: {},
            cache: false,
            success:function(data){

                //do something with the result

            },
            complete: myLongPoll, 
            async : false,
            timeout: 5000
        });
   //Doesn't matter how long it took the ajax call, 1 milisec or 
   //5 seconds (timeout), the next call will only happen after 2 seconds
   }, 2000);

こうすることで、次の通話が始まる前に確実に$.ajax()通話を終了できます。console.log()これは、呼び出しの前に単純なものを追加し、呼び出しの後に別のものを追加することで証明できます$.ajax()

于 2014-05-14T14:20:59.957 に答える
1

スタックの深さは 4 ~ 5 が適切です。setTimeoutおよび$.ajaxは非同期呼び出しであり、すぐに戻ります。コールバックは、空のコール スタックでブラウザによって後で呼び出されます。ロング ポーリングを同期的に実装することはできないため、この再帰的なアプローチを使用する必要があります。繰り返しにする方法はありません。

この速度低下の理由は、コードにメモリ リークがあるためだと思われます。リークは$.ajax、jQuery によるもの (ほとんどありません) またはprocessResults呼び出しによるものである可能性があります。

于 2010-01-19T16:20:19.410 に答える