Цепочки промисов

jQuery предоставляет собственный механизм работы с асинхронными операциями через объект Deferred, который реализует паттерн промисов. Этот механизм позволяет последовательно выполнять асинхронные действия, обрабатывать успешное завершение и ошибки, а также комбинировать несколько операций в цепочки.

Создание Deferred и получение промиса

Объект Deferred создаётся вызовом:

var deferred = $.Deferred();

Чтобы получить промис из этого объекта, используется метод promise():

var promise = deferred.promise();

Промис предоставляет методы для подписки на завершение операции:

  • done(callback) — вызывается при успешном завершении.
  • fail(callback) — вызывается при ошибке.
  • always(callback) — вызывается в любом случае.

Простая цепочка

Методы then, done и fail позволяют создавать цепочки:

$.ajax("/data.json")
  .then(function(response) {
      console.log("Данные получены:", response);
      return $.ajax("/additional.json");
  })
  .then(function(additionalData) {
      console.log("Дополнительные данные:", additionalData);
  })
  .fail(function(error) {
      console.error("Произошла ошибка:", error);
  });

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

Возврат значений и промисов внутри then

Метод then может возвращать как обычное значение, так и новый промис. Это позволяет строить более сложные последовательности:

$.ajax("/user.json")
  .then(function(user) {
      return $.ajax("/orders.json?userId=" + user.id);
  })
  .then(function(orders) {
      console.log("Список заказов:", orders);
  });

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

Обработка ошибок в цепочках

jQuery позволяет обрабатывать ошибки на любом шаге цепочки. Методы fail и then(null, onRejected) выполняют одну и ту же функцию:

$.ajax("/data.json")
  .then(
      function(data) { console.log("Данные:", data); },
      function(err) { console.error("Ошибка загрузки:", err); }
  );

При использовании цепочек часто применяется общий блок fail в конце, чтобы централизованно обработать все ошибки.

Объединение нескольких промисов

Метод $.when позволяет запускать несколько асинхронных операций параллельно и получать результат, когда все они завершены:

$.when($.ajax("/users.json"), $.ajax("/orders.json"))
  .then(function(users, orders) {
      console.log("Пользователи:", users[0]);
      console.log("Заказы:", orders[0]);
  })
  .fail(function() {
      console.error("Ошибка при загрузке данных");
  });

Метод $.when возвращает промис, который считается выполненным, если все переданные промисы завершились успешно. Если хотя бы один промис завершается ошибкой, срабатывает блок fail.

Цепочки с промежуточной трансформацией данных

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

$.ajax("/users.json")
  .then(function(users) {
      return users.map(user => user.id);
  })
  .then(function(userIds) {
      return $.when(...userIds.map(id => $.ajax("/orders.json?userId=" + id)));
  })
  .then(function(...orders) {
      console.log("Все заказы пользователей:", orders.map(o => o[0]));
  });

Здесь сначала извлекаются идентификаторы пользователей, затем для каждого идентификатора загружаются заказы, а в конце объединяются результаты всех промисов.

Особенности использования цепочек в jQuery

  1. Метод then возвращает новый промис — цепочки не изменяют исходный объект Deferred.
  2. Обработка ошибок должна быть учтена на каждом уровне, либо централизованно через fail.
  3. Совместимость с $.when позволяет комбинировать последовательные и параллельные операции.
  4. Промежуточные значения можно трансформировать, возвращая их в следующую цепочку через then.

Преимущества цепочек

  • Упрощение кода по сравнению с вложенными колбэками.
  • Централизованная обработка ошибок.
  • Лёгкая комбинация последовательных и параллельных асинхронных операций.
  • Возможность трансформации данных на каждом шаге цепочки.

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