AngularJS: Использование сервиса $q (как работать с deferred и promise объектами)

Категория: AngularJS

Разбираемся с сервисом $q и объектами Deferred, Promise.

Термины

$q
Сервис для управления асинхронными операциями (HTTP запросами или другими действиями).
Deferred
Отложенный (defer - откладывать, отложить). Объект предоставляет методы управления состоянием выполнения асинхронной операции (которую отражает объект promise вложенный в Deferred).
Promise
Обещание. Объект, в котором мы регистрируем callback-обработчики разных статусов завершения операции (не обязательно HTTP запроса).

Сервис $q предназначен для управления любыми асинхронными операциями.

Создание deferred объекта

Это основной метод использования сервиса.

Deferred объект

Получить объект отложенного действия/запроса:

var deferred = $q.defer(); // дословно мы говорим: запрос - отложить

Еще раз - deferred объект обеспечивает API для управления состоянием асинхронной операции.

Теперь мы можем управлять состоянием объекта отложенного действия/запроса:

deferred.resolve('<success data>'); // вызываем при успешном выполнении действия/запроса
deferred.reject('<error data>');    // вызываем при ошибке выполнения действия/запроса
deferred.notify('<progress data>'); // мы можем сообщить promise обработчику о каком-то промежуточном состоянии операции
deferred.promise; // в объекте promise мы регистрируем обработчики разных состояний

Promise объект

После завершения выполнения асинхронной операции (действия/запроса) будут запущенны соответствующие обработчики:

var promise = deferred.promise;

promise.then(function(response) {
    console.log('SUCCESS: ', response);
}, function(response) {
    console.log('ERROR: ', response);
}, function(response) {
    console.log('PROGRESS STATUS: ', response);
});

Обработчик ошибок можно установить с помощью catch():

promise.catch(function(response) {
  console.log('ERROR', response);
});

Также можно установить обработчик для любого завершенного состояния операции/запроса:

promise.finally(function(response) {
  console.log('FINALLY', response);
});

Короткая запись для управления состоянием операции

Вы можете сразу же установить ф-ции управления состоянием операции и вернуть объект Promise:

var promise = $q(function(resolve, reject) {
  resolve('Success'); 
  // OR
  reject('Error');
});

Прочие методы API сервиса $q

Создать Promise с ошибочным статусом выполнения операции:

var promise = $q.reject('<reason>');

Преобразовать любое значение в promise (может принимать jQueryPromise и конвертировать его в Promise/A+):

var promise = $q.when(isAsyncFn ? asyncFn() : 44).then(callback, errback, progressback);

Метод when() определяет что передан promise по наличию в объекте ф-ции `then`, если она есть у переданного объекта - то when() вытаскивает из промиса колбеки и заворачивает их в промис стандарта Promises/A+.

Объединяет несколько Promise объектов в один, который будет завершен, когда все promise-объекты будут завершены:

var promise = $q.all(promises); // запускает параллельную обработку всех promises

Возвращает первый выполненный Promise:

var promise = $q.race(promises);

Дополнения

Создание нового promise и проброс ошибок

При использовании вложенных асинхронных обработчиков (promises) - нужно "пробрасывать наверх" ответ дочерних промисов:

var newPromise = promise.then(function(response) {
  return otherAsyncFn(response);
});

Метод then() всегда возвращает новый promise объект с данными переданными из тела then-функции.

Примечание

Для поддержки IE<9 нужно вызывать методы catch и finally как ключи массива (это зарезервированными имена):

promise['catch'](function() { ... });
promise['finally'](function() { ... });

#deferred and promise in javascript, #angular $q service, #промисы в angularjs, #angular async request

категория: AngularJS