Подтвердить что ты не робот

Данные в реальном времени в сетке - лучший метод

Что для вас лучше подходит для отображения данных в реальном времени (фондовая биржа, погода,...) в сетке?
Я использую этот метод:

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

Ответ 1

Я нахожу ваш вопрос очень интересным. Я думаю, этот вопрос может быть интересен для многих других пользователей. Так что +1 от меня.

Использование setInterval позволяет мне наилучшим образом использовать общий случай, не зависящий от браузера. Вы должны сохранить результат setInterval в переменной, чтобы иметь возможность использовать clearInterval, чтобы остановить его.

Еще одним небольшим улучшением было бы использование [{current:true}] (см. ответ для деталей) в качестве второго параметра trigger:

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

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

Он сохранит выбор во время перезагрузки сетки.

Многие новые веб-браузеры теперь поддерживают WebSocket. Поэтому было бы лучше использовать этот способ, если веб-браузер поддерживает его. В способе можно пропустить ненужную перезагрузку сетки в случае, если данные не изменены на сервере и не предотвращают постоянный пул сервера.

Мне кажется, что еще один общий способ выглядит очень интересным. Если бы кто-то использовал временную метку последних изменений данных сетки, можно было бы проверить, изменены ли данные. Для этой цели можно использовать ETag или какой-то общий дополнительный метод на сервере.

Текущий успех обратный вызов jQuery.ajax, которые заполняют jqGrid, позволяют использовать обратный вызов beforeProcessing для изменения ответа сервера, но он не позволяет остановить обновление jqGrid на основе значения jqXHR.satus (это будет xhr.status в текущем коде jqGrid). Небольшая модификация строка кода jqGrid позволит вам остановить обновление jqGrid в случае неизмененных данных на сервере. Можно либо протестировать textStatus (st в текущем коде jqGrid) для "notmodified", либо проверить jqXHR.satus (xhr.status в текущем коде jqGrid) для 304. Важно, чтобы для использования сценария вы должны использовать опцию prmNames: { nd:null } и установить ETag и Cache-Control: private, max-age=0 (см. здесь, здесь и здесь за дополнительную информацию).

ОБНОВЛЕНО. Я попытался создать демонстрационный проект на основе моих последних предложений и выяснил, что это не так просто, как я описал выше. Тем не менее я заставил его работать. Трудность заключалась в том, что невозможно увидеть код 304 из ответа сервера внутри jQuery.ajax. Причиной было следующее место в Спецификация XMLHttpRequest

Для ответов 304 Not Modified, которые являются результатом действия агента пользователя генерируемый условный запрос, пользовательский агент должен действовать так, как если бы сервер дал ответ 200 OK с соответствующим контентом. Пользовательский агент должен позволять заголовкам запросов автора переопределять автоматический кеш (например, If-None-Match или If-Modified-Since), и в этом случае 304 Не модифицированные ответы должны проходить через.

Итак, вы видите 200 OK внутри success обработчика $.ajax вместо 304 Not Modified из ответа сервера. Кажется, что XMLHttpRequest возвращает только полный ответ из кэша, включая все HTTP-заголовки. Поэтому я решил изменить анализ кэшированных данных, просто сохранив ETag из последнего HTTP-ответа в качестве нового параметра jqGrid и проверив ETag нового ответа с сохраненными данными.

Я видел, что вы используете PHP (который я не использую:-(). Тем не менее, я могу читать и понимать PHP-код. Надеюсь, вы можете точно так же прочитать код С# и понять основную идею. быть в состоянии реализовать то же самое в 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");
}

Строка $("#isProcessed").text("Processed"); или строка $("#isProcessed").text("Processing skipped!!!"); установили текст "Processed" или "Processing skipped!!!" в div, который я использовал для визуального указания того, что данные с сервера использовались для заполнения сетки.

В демоверсии я показываю две сетки с теми же данными. Первая сетка, которую я использую для редактирования данных. Вторая сетка извлекает данные с сервера каждую секунду. Если данные не изменены на сервере, 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}]); каждую секунду. Страница выглядит как

enter image description here

Я отметил наиболее важные части в нижней части страницы с помощью цветных полей. Если один параметр loadui: "disable", то во время вытягивания сервера никто не видит никаких изменений в сетке. Если кто-то прокомментировал вариант, что в течение очень короткого времени вы увидите div "Загрузка...", но не содержит сетки, мерцает.

После запуска "Autorefreshing" вы увидите в основном изображение, как показано ниже.

enter image description here

Если кто-то изменит какую-то строку в первой сетке, вторая сетка будет изменена в секунду, а одна увидит текст "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.

Вы можете загрузить проект здесь.

ОБНОВЛЕНО: я отправил запрос функции, чтобы позволить beforeProcessing разорвать обработку ответа сервера на возвращая значение false. Соответствующие изменения уже включены (см. здесь) в главном коде jqGrid. Поэтому следующий выпуск jqGrid будет включать его.