Метод $.when()

Метод $.when() является мощным инструментом для работы с асинхронными операциями в jQuery. Он позволяет объединять несколько объектов Deferred или промисов, обеспечивая удобное управление их завершением и обработкой результатов. Основная цель метода — синхронизация нескольких асинхронных задач и выполнение определённого кода после того, как все задачи будут выполнены.


Основы работы с $.when()

Синтаксис метода:

$.when(deferred1, deferred2, ..., deferredN).done(function(result1, result2, ..., resultN) {
    // код, выполняемый после завершения всех задач
});
  • Аргументы: один или несколько объектов Deferred или промисов.
  • Возвращаемое значение: объект Deferred, на котором можно вызвать методы .done(), .fail(), .always().
  • Поведение: если все переданные Deferred объекты разрешаются, вызывается функция .done(). Если хотя бы один отклоняется, срабатывает .fail().

Метод позволяет объединять результаты нескольких асинхронных операций и обрабатывать их в едином месте.


Работа с одним Deferred

Даже при передаче одного объекта Deferred $.when() создаёт цепочку промисов, что упрощает обработку результата:

var deferred = $.Deferred();

$.when(deferred).done(function(value) {
    console.log("Задача выполнена с результатом:", value);
});

deferred.resolve("успех");

В примере Deferred разрешается методом .resolve(), после чего срабатывает обработчик .done().


Работа с несколькими Deferred

Метод особенно полезен при работе с нескольких асинхронных операций:

var request1 = $.ajax("/api/data1");
var request2 = $.ajax("/api/data2");

$.when(request1, request2).done(function(response1, response2) {
    console.log("Данные 1:", response1[0]);
    console.log("Данные 2:", response2[0]);
});

Особенности:

  • Каждый результат AJAX-запроса передаётся в виде массива: [данные, текстовый статус, jqXHR].
  • Порядок аргументов в .done() соответствует порядку передачи Deferred в $.when().
  • Если один из запросов завершится с ошибкой, срабатывает .fail():
$.when(request1, request2).fail(function() {
    console.log("Один или несколько запросов не удались");
});

Использование с динамическим количеством Deferred

$.when() позволяет работать с массивами Deferred через оператор apply:

var requests = [
    $.ajax("/api/data1"),
    $.ajax("/api/data2"),
    $.ajax("/api/data3")
];

$.when.apply($, requests).done(function() {
    for (var i = 0; i < arguments.length; i++) {
        console.log("Данные", i + 1, ":", arguments[i][0]);
    }
});

Это полезно, когда количество асинхронных операций заранее неизвестно. Все результаты доступны через объект arguments, каждый элемент которого содержит данные, статус и объект jqXHR.


Методы для работы с $.when()

Метод возвращает объект Deferred, поэтому доступны стандартные методы Deferred:

  • .done(callback) — вызывается при успешном завершении всех задач.
  • .fail(callback) — вызывается при неудаче хотя бы одной задачи.
  • .always(callback) — вызывается в любом случае, независимо от успеха или ошибки.
  • .then(doneCallback, failCallback) — комбинированный метод, позволяющий обработать успех и ошибку одновременно.

Пример с использованием .then():

$.when(request1, request2).then(
    function(r1, r2) {
        console.log("Все запросы выполнены успешно");
    },
    function() {
        console.log("Ошибка в одном из запросов");
    }
);

Особенности работы с null и обычными значениями

Если в $.when() передаётся не Deferred, а обычное значение, оно автоматически преобразуется в мгновенный успешный промис:

$.when(42).done(function(value) {
    console.log(value); // 42
});

Это позволяет смешивать асинхронные и синхронные данные без дополнительной обработки.


Практическое применение

Метод $.when() чаще всего используется для:

  • Синхронизации нескольких AJAX-запросов.
  • Координации анимаций и асинхронных эффектов jQuery.
  • Создания цепочек обработки данных, получаемых асинхронно.
  • Объединения асинхронных операций с разной длительностью выполнения.

Пример с анимациями:

var anim1 = $("#box1").fadeIn().promise();
var anim2 = $("#box2").slideDown().promise();

$.when(anim1, anim2).done(function() {
    console.log("Все анимации завершены");
});

Метод .promise() превращает любую анимацию в объект Deferred, что позволяет использовать их совместно с $.when().


Метод $.when() обеспечивает мощный и гибкий механизм управления асинхронностью в jQuery, объединяя Deferred объекты, AJAX-запросы, анимации и обычные значения в единый поток обработки. Он упрощает синхронизацию и обработку результатов сразу нескольких операций, делая код более читаемым и поддерживаемым.