Всем добрый день.
Раздумывая над вопросом фонового обновления информации, мне пришла в голову одна идея.
Суть задачи — мы находимся на странице списка новостей. Необходимо обновлять список по мере поступления новых новостей. Серверный язык PHP
Рассмотрим классический вариант через постоянные запросы аяксом:
1) Клиент посылает аякс запрос на сервер, например по адресу — /ajax/get_upades&time=xxxxxx
2) PHP смотрит есть ли в базе данных записи, новее чем time
3) Если есть выбирает их и возвращает
4) Если нет ничего не возвращает
В этом случае мы вынуждены постоянно дергать PHP и БД для ответа на вопрос, есть ли новые данные?
Мне очень не понравилась эта идея.
Варианты с long polling мне тоже не понравились в связи с различными трудностями реализации и удержанием большого к-ва открытых соединений
Тогда я решил почему бы не переложить задачу по определению наличия новых данных на сам сервер, полностью минуя PHP
Суть идеи заключается в следующем
Клиент постоянно пингует пустой файл-маркер. Назовем его /ping/new_news
Сервер при отдаче файла посылает заголовок — ETag вида «10aa0f-7-4b877e2d4941c». Это один из заголовков принимающих участие в механизме кеширования. ETag рассчитывается на основании информации inode, size и mtime файла. Т.е. при изменение mtime (времени изменения файла) сервер будет посылать другой ETag.
Все что нам нужно это при вставке новой новости обновить mtime файла например ф-цией touch(), а лучше создать триггер в базе на вставку записи и менять файл
Далее мы пишем небольшой класс. Назовем его Updater
var Updater = function(){
this.params = {
period: 3000,
url: '',
onModified: function(data,x){},
bgPause: false
};
this.interval = null;
this.ETag = '';
this.init = function(params){
var me = this;
this.params = $.extend(this.params, params);
if(this.params.bgPause){
$(window).blur(function(){ me.pause() });
$(window).focus(function(){ me.resume() });
}
};
this.start = function(){
var me = this;
this.interval = setInterval(function(){ me.doUpdate() }, this.params.period);
};
this.doUpdate = function(){
var me = this;
$.ajax(this.params.url, {
success: function(data,status,x){
if(me.ETag != x.getResponseHeader('ETag')){
me.params.onModified(data,x);
}
me.ETag = x.getResponseHeader('ETag');
}
});
};
this.pause = function(){
clearInterval(this.interval);
this.interval = null;
};
this.resume = function(){
if(this.interval != null) return;
this.start();
};
};
Скрипт посылает в цикле запросы на указанный урл, при обнаружении изменения Etag вызывается onModified задача которого уже послать запрос на получения самих данных.
Для уменьшения к-ва запросов мы перестаем пинговать сервер, когда пользователь не видит нашу страницу
if(this.params.bgPause){
$(window).blur(function(){ me.pause() });
$(window).focus(function(){ me.resume() });
}
Вот такая вот идея пришла в голову. Выслушаю Вашу критику, идеи, предложения. Всем спасибо