AngularJS: Использование сервиса $q (как работать с deferred и promise объектами)
Разбираемся с сервисом $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