Joomla 1.5: Использование Ajax - Обработка на стороне клиента.

Joomla 1.5: Использование Ajax - Обработка на стороне клиента.

Индекс материала
Joomla 1.5: Использование Ajax
Обработка на стороне сервера.
Обработка на стороне клиента.
Обходим политику единого источника
Все страницы

Правильная обработка асинхронных Ajax - ответов в MooTools

Легко забыть, что начальная буква "А" в слове "Ajax" обозначает "асинхронный", что означает, что, как только пользователь инициировал запрос Ajax, он так же имеет право делать другие вещи c интерфейсом, в том числе совершать и ...другие Ajax - запросы.

Как создатель веб-приложений вы должны принять во внимание, что ответы на эти запросы могут поступать обратно совершенно не в том же порядке, в котором они были сделаны. Если игнорировать это недоразумение, оно может иметь печальные последствия для пользователей.

Например, в типичной реализации Ajax, где пользователь выбирает страну из выпадающего списка стран, а затем представлен раскрывающийся список регионов внутри этой страны, вызов Ajax производится всякий раз, когда изменилась страна. Ответом на этот запрос будет список регионов выбранной страны. Но предположим, что пользователь несколько раз быстро делает выбор, что довольно просто сделать с помощью клавиатуры.

Допустим пользователь нажимает клавишу "U" и первой страной, которая отобразится в списке - будет "Uganda". Это не то, что хочет пользователь, и он нажимает клавишу "U" ещё несколько раз, пока он получает "United Kingdom", затем еще раз, чтобы в итоге получить то, что он действительно хотел: "United States". Эти действия вызывают целый ряд последовательностей Ajax вызовов, с последним из которых является выбор "United States".

Предположим, что ответ на запрос "United Kingdom" по некоторым причинам задерживается. Это может быть из-за нагрузки на сервер, или это могут быть задержки в сети. Но по какой то причине, он прибыл после ответа на запрос "United States". В итоге пользователю будет предложен список регионов из "United Kingdom", хотя его выбор был "United States". Такое поведение явно нежелательно.

Конечно были предложены различные способы для предотвращения этого "эффекта", в том числе и те, которые затавляют сервер обрабатывать запросы строго в порядке поступления (который, кстати не исключает возможности задержек в сети на обратном пути, и как следствие все еще остаётся возможность прихода ответов клиенту в неправильной последовательности ).

Тем не менее, решение, предложенное ниже, в силу того, что оно довольно просто, оно не требует никаких специальных приёмов на сервере, и оно справляется со всеми проблемами. Идея заключается в построении и поддержании простой очереди, содержащий все запросы, которые были сделаны, на выходе мы получаем ответы сервера в правильной последовательности, независимо от порядка их поступления.

Но должен быть какой-то способ определить, является ли конкретный запрос выполненным или нет. Для этого вы можете расширить MooTools Ajax "класс" следующим образом:

// Расширяем MooTools Ajax "класс" :
Ajax = Ajax.extend({
 
    initialize: function( url, options ) {
        this.parent( url, options );
        this.ready = false;
        this.output = '';
    },
 
    onComplete: function() {
    	this.ready = true;
    	this.parent();
    }
 
});

Это добавит два дополнительных свойства к "классу" Ajax:

  • ready - это логический флаг - доступен ли ответ на запрос или нет
  • output - контейнер для хранения ответа.

Теперь нужно создать механизм, реализующий очередь для хранения запросов. Каждый новый запрос будет помещён в очередь а завершённые запросы будут извлекается из очереди. Фокус в том, что если более новый запрос завершается быстрее чем более старые, то этот ( более новый ) запрос остается в очереди, а не удаляется из последовательности. Очередь это простой массив, объявленный в глобальной области:

var AJAX_QUEUE = [];

Код window.addEvent модифицирован таким образом, что объект Ajax помещается в очередь перед запросом:

window.addEvent( 'domready', function() {
 
	$('drop-down').addEvent( 'change', function() {
 
		$( 'ajax-container' ).empty().addClass( 'ajax-loading' );
		var url = 'index.php?option=com_component&args=whatever';
		var a = new Ajax( url, {
			method: 'get',
			onComplete: function( response ){
 
			// Здесь код функции Ajax onComplete...
 
			}
		});
		AJAX_QUEUE.push( a );
		a.request();
	});
});

Затем нужно добавить некоторый дополнительный код к функции onComplete, которая вытолкнет завершенные запросы из очереди, но только в правильном порядке:

// Сохраняем ответ в Ajax объект.
this.output = response;
 
// Обработка очереди:
while ( AJAX_QUEUE.length ) {
 
	// Если старший запрос в очереди не обработан - ничего не делаем:
	if ( !AJAX_QUEUE[0].ready ) break;
 
	// Выталкиваем запрос из очереди:
	r = AJAX_QUEUE.shift();
 
	// Выводим данные только когда очередь пуста:
	if ( !AJAX_QUEUE.length ) {
		$('ajax-container').removeClass('ajax-loading').setHTML(r.output);
	} 
}

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



Добавить комментарий


Защитный код
Обновить



Кто на сайте
Сейчас 104 гостей онлайн