18

リアルタイム データ (証券取引所、天気など) をグリッドで表示するためのより良いアプローチは何ですか?
私はこの方法を使用します:

setInterval(function(){
      jQuery("#list1").trigger('reloadGrid');
}, 5000);
4

1 に答える 1

16

あなたの質問はとても興味深いと思います。この質問は、他の多くのユーザーにとって興味深いものになると思います。だから私から+1。

setIntervalブラウザに依存しない一般的なケースでは、 Seamsの使用が最善の方法です。setInterval結果を変数に保存して、clearInterval停止に使用できるようにする必要があります。

もう1つの小さな改善点は、の2番目のパラメーターとして[{current:true}](詳細については回答triggerを参照)を使用することです。

var $grid = jQuery("#list1"), timer;

timer = setInterval(function () {
    $grid.trigger('reloadGrid', [{current: true}]);
}, 5000);

グリッドのリロード中に選択を保存します。

多くの新しい Web ブラウザーがWebSocketをサポートするようになりました。そのため、Web ブラウザがサポートしている場合は、その方法を使用することをお勧めします。サーバー上でデータが変更されていない場合に備えて、不要なグリッドのリロードをスキップし、サーバーの永続的なプールを防ぐことができます。

もう1つの一般的な方法も非常に興味深いようです。グリッド データの最後の変更のある種のタイムスタンプを使用すると、データが変更されたかどうかを確認できます。この目的のために、サーバー上でETagまたは何らかの一般的な追加メソッドを使用できます。

jqGridを埋める jQuery.ajaxの現在の成功コールバックを使用すると、コールバックを実装してサーバーの応答を変更できますが、値に基づいてjqGrid の更新を停止することはできません(現在の jqGrid コードにあります)。jqGridのコードを少し変更すると、サーバー上のデータが変更されていない場合に、jqGrid の更新を停止できます。304を( jqGrid の現在のコードで)テストするか、 (現在の jqGrid コードで)テストすることができます。シナリオを使用するには、オプションとセットを使用する必要があることが重要です。beforeProcessingjqXHR.satusxhr.statustextStatusst"notmodified"jqXHR.satusxhr.statusprmNames: { nd:null }ETagCache-Control: private, max-age=0(追加情報については、ここここ、およびここを参照してください)。

更新: 最後の提案に基づいてデモ プロジェクトを作成しようとしましたが、上記のように簡単ではないことがわかりました。それにもかかわらず、私はそれを機能させました。問題は、jQuery.ajax 内のサーバー応答から 304 コードを確認できないためです。その理由は、XMLHttpRequest 仕様の次の場所でした。

ユーザー エージェントが生成した条件付き要求の結果である304 Not Modified応答の場合、ユーザー エージェントは、サーバーが適切な内容で200 OK応答を返したかのように動作する必要があります。ユーザー エージェントは、オーサー リクエスト ヘッダーが自動キャッシュ検証 ( If-None-MatchまたはIf-Modified-Sinceなど) をオーバーライドできるようにする必要があります。この場合、 304 Not Modifiedレスポンスを渡す必要があります。

そのため、サーバー応答からの304 Not Modifiedの代わりに、ハンドラー内に200 OKステータスが表示されます。すべての HTTP ヘッダーを含むキャッシュから完全な応答だけが返されるようです。そこで、最後の HTTP 応答から保存したキャッシュ データの分析を新しい jqGrid パラメータとして変更し、保存されたデータを使用して新しい応答をテストすることにしました。success$.ajaxXMLHttpRequestETagETag

あなたが PHP を使っているのを見ました (私は :-( は使いません)。それにもかかわらず、私は PHP コードを読んで理解することができます。あなたが同じように C# コードを読んで、主なアイデアを理解できることを願っています。 PHPで同じものを実装します。

今、私がしたことを説明します。まず、コールバックを使用する jqGrid ソース コードの行を変更しました。beforeProcessing

if ($.isFunction(ts.p.beforeProcessing)) {
    ts.p.beforeProcessing.call(ts, data, st, xhr);
}

if ($.isFunction(ts.p.beforeProcessing)) {
    if (ts.p.beforeProcessing.call(ts, data, st, xhr) === false) {
        endReq();
        return;
    }
}

false を返すことbeforeProcessingで、データの更新をスキップしたり、データの処理をスキップしたりできます。デモで使用した実装はbeforeProcessing、使用法に基づいていますETag

beforeProcessing: function (data, status, jqXHR) {
    var currentETag = jqXHR.getResponseHeader("ETag"), $this = $(this),
        eTagOfGridData = $this.jqGrid('getGridParam', "eTagOfGridData");
    if (currentETag === eTagOfGridData) {
        $("#isProcessed").text("Processing skipped!!!");
        return false;
    }
    $this.jqGrid('setGridParam', { eTagOfGridData: currentETag });
    $("#isProcessed").text("Processed");
}

サーバーからのデータがグリッドを埋めるために使用されたことを視覚的に示すために使用した div 内の行$("#isProcessed").text("Processed");または行$("#isProcessed").text("Processing skipped!!!");セット"Processed"またはテキスト。"Processing skipped!!!"

デモでは、同じデータを持つ 2 つのグリッドを表示します。データの編集に使用する最初のグリッド。2 番目のグリッドは、毎秒サーバーからデータをプルします。サーバーでデータが変更されていない場合、HTTP トラフィックは次のようになります。

HTTP リクエスト:

GET http://localhost:34336/Home/DynamicGridData?search=false&rows=10&page=1&sidx=Id&sord=desc&filters= HTTP/1.1
X-Requested-With: XMLHttpRequest
Accept: application/json, text/javascript, */*; q=0.01
Referer: http://localhost:34336/
Accept-Language: de-DE
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; LEN2)
Host: localhost:34336
If-None-Match: D5k+rkf3T7SDQl8b4/Y1aQ==
Connection: Keep-Alive

HTTP 応答:

HTTP/1.1 304 Not Modified
Server: ASP.NET Development Server/10.0.0.0
Date: Sun, 06 May 2012 19:44:36 GMT
X-AspNet-Version: 4.0.30319
X-AspNetMvc-Version: 2.0
Cache-Control: private, max-age=0
ETag: D5k+rkf3T7SDQl8b4/Y1aQ==
Connection: Close

したがって、データが変更されていない場合、サーバーからデータは転送されません。データが変更された場合、HTTP ヘッダーが開始され、新しい変更されたデータとデータのページ自体がHTTP/1.1 200 OK含まれます。ETag

ナビゲーターの「更新」ボタンを使用して手動で、または毎秒実行される「自動更新を開始」ボタンを使用して、グリッドのデータを更新できます$grid1.trigger('reloadGrid', [{ current: true}]);。ページは次のようになります

ここに画像の説明を入力

ページの下部にある最も重要な部分をカラー ボックスでマークしました。1 つのloadui: "disable"オプションの場合、サーバーのプル中にグリッドに変更がまったく表示されません。オプションにコメントすると、「読み込み中...」という div が非常に短時間表示されますが、含まれるグリッドはちらつきません

「自動リフレッシュ」の開始後、主に以下のような画像が表示されます

ここに画像の説明を入力

最初のグリッドの行を変更すると、2 番目のグリッドが 1 秒で変更され、テキストが表示され、さらに 1 秒でテキストに"Processed"変更され"Processing skipped!!!"ます。

サーバー側の対応するコード (私は ASP.NET MVC を使用しました) は、主に次のとおりです。

public JsonResult DynamicGridData(string sidx, string sord, int page, int rows,
                                  bool search, string filters)
{
    Response.Cache.SetCacheability (HttpCacheability.ServerAndPrivate);
    Response.Cache.SetMaxAge (new TimeSpan (0));

    var serializer = new JavaScriptSerializer();
    ... - do all the work and fill object var result with the data

    // calculate MD5 from the returned data and use it as ETag
    var str = serializer.Serialize (result);
    byte[] inputBytes = Encoding.ASCII.GetBytes(str);
    byte[] hash = MD5.Create().ComputeHash(inputBytes);
    string newETag = Convert.ToBase64String (hash);
    Response.Cache.SetETag (newETag);
    // compare ETag of the data which already has the client with ETag of response
    string incomingEtag = Request.Headers["If-None-Match"];
    if (String.Compare (incomingEtag, newETag, StringComparison.Ordinal) == 0) {
        // we don't need return the data which the client already have
        Response.SuppressContent = true;
        Response.StatusCode = (int)HttpStatusCode.NotModified;
        return null;
    }

    return Json (result, JsonRequestBehavior.AllowGet);
}

ASP.NET MVC だけでなく、使用する人にもコードの主なアイデアが明確になることを願っています。

プロジェクトはこちらからダウンロードできます。

更新: 値を返すことでサーバー応答の処理を中断できるようにする機能要求を投稿しました。対応する変更は、メインの jqGrid コードに既に含まれています (こちらを参照)。したがって、jqGrid の次のリリースにはそれが含まれます。beforeProcessingfalse

于 2012-05-05T12:45:13.703 に答える