Deferred объект в jQuery

В jQuery 1.5 появился новый объект deferred, призванный облегчить работу с асинхроными действиями.

Давайте рассмотрим пример работы с ajax запросами, где нам надо сделать 2 последовательных асинхронных запроса.


// Дожидаемся загрузки документа
$(document).ready(function() {
	// Выполняем первый запрос
	$.get("get-user-id.php", {dataType: "json"})
	.done(function(data) {
	    // Если первый запрос был успешно выполнен, выполняем второй запрос
	    $.get("get-user-name-by-id.php", {userId: data.userId}, function() {}, "json")
	    .done(function(data) {
	    	// Если второй запрос был успешно выполнен, выводим приветствие
	    	console.log("Здравствуйте " + data.userName);
	    })
		.fail(function() {
			// Если возникли проблемы со вторым запросом, выводим ошибку
			console.log("Ошибка при получении имени пользователя");
		});
	})
	.fail(function() {
		// Если возникли проблемы с первым запросом, выводим ошибку
		console.log("Ошибка при получении id пользователя");
	});
});

Каждый последующий запрос находится внутри callback функции предыдущего, поэтому вложенность функций растет.
К томуже для каждого запроса нам надо писать свой обработчик ошибок, что не всегда то и нужно.
Как вы наверное уже поняли, решить эти проблемы и призван объект deferred.
Давайте перепишем этот код с использованием jQuery объекта deferred.


// Дожидаемся загрузки документа
$.when($(document).ready())
// Выполняем первый запрос
.then($.get("get-user-id.php", {dataType: "json"}))
// Если первый запрос был успешно выполнен, выполняем второй запрос
.then(function(data) {
    return $.get("get-user-name-by-id.php", {userId: data.userId}, function() {}, "json");
})
// Если второй запрос был успешно выполнен
.done(function(data) {
	console.log("Здравствуйте " + data.userName);
})
// Если возникли проблемы, хоть в одном запросе, выводим ошибку
.fail(function() {
    console.log("Ошибка при получении id или имени пользователя");
});

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

Давайте рассмотрим еще один пример.
Нам надо отобразить сообщение когда пользователь нажмет на обоих кнопках в произвольном порядке. С deferred объектом это проще простого.


<button id="button1">Button 1</button>
<button id="button2">Button 2</button>

<script type="text/javascript">
// Создаем Deferred объект для каждой кпопки
var deferred1 = $.Deferred(),
	deferred2 = $.Deferred();

// Переводим соответствуюший deferred объект в статус resolve при клике на кнопке
$("#button1").click(deferred1.resolve);
$("#button2").click(deferred2.resolve);

// Когда оба deferred объекта будут в статусе resolve, выводим сообщение
$.when(deferred1, deferred2).done(function() {
	console.log("Ready!");
});
</script>

Автор: http://www.nika.org.ua
Дата: 16.10.13

Копирование материалов без указания "Автор: http://www.nika.org.ua" запрещено!