Улучшить эту документацию Просмотреть исходный код $q
- сервис в модуле ng
Сервис, который помогает выполнять функции асинхронно и использовать их возвращаемые значения (или исключения) по завершении обработки.
Это реализация объектов обещаний/отложенных объектов, вдохновленная Q Криса Ковала.
Предложение CommonJS по обещаниям описывает обещание как интерфейс для взаимодействия с объектом, представляющим результат действия, выполняемого асинхронно, и который может быть завершен или нет в любой момент времени.
С точки зрения обработки ошибок, API отложенных объектов и обещаний аналогичны ключевым словам try, catch и throw в синхронном программировании.
// for the purpose of this example let's assume that variables `$q`, `scope` and `okToGreet`
// are available in the current lexical scope (they could have been injected or passed in).
function asyncGreet(name) {
var deferred = $q.defer();
setTimeout(function() {
deferred.notify('About to greet ' + name + '.');
if (okToGreet(name)) {
deferred.resolve('Hello, ' + name + '!');
} else {
deferred.reject('Greeting ' + name + ' is not allowed.');
}
}, 1000);
return deferred.promise;
}
var promise = asyncGreet('Robin Hood');
promise.then(function(greeting) {
alert('Success: ' + greeting);
}, function(reason) {
alert('Failed: ' + reason);
}, function(update) {
alert('Got notification: ' + update);
});
Вначале может не быть очевидно, почему эта дополнительная сложность стоит усилий. Выгода заключается в гарантиях, которые предоставляют API обещаний и отложенных объектов, см. https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.
Кроме того, API обещаний позволяет для композиции, что очень сложно сделать с традиционным подходом обратного вызова (CPS). Для получения дополнительной информации см. документацию Q, особенно раздел о последовательном или параллельном объединении обещаний.
API отложенных объектов
Новый экземпляр отложенного объекта создается путем вызова $q.defer().
Цель объекта отложенного объекта заключается в предоставлении доступа к связанному экземпляру обещания, а также API, которые можно использовать для сигнализации об успешном или неудачном завершении, а также о статусе задачи.
Методы
-
resolve(value)— разрешает производное обещание сvalue. Если значение представляет собой отказ, созданный с помощью$q.reject, обещание будет отклонено вместо этого. -
reject(reason)— отклоняет производное обещание сreason. Это эквивалентно его разрешению с помощью отказа, созданного с помощью$q.reject. -
notify(value)- предоставляет обновления о статусе выполнения обещания. Это может быть вызвано несколько раз до тех пор, пока обещание не будет разрешено или отклонено.
Свойства
- promise —
{Promise}— объект обещания, связанный с этим отложенным объектом.
API обещаний
Новый экземпляр обещания создается при создании экземпляра отложенного объекта и может быть получен путем вызова deferred.promise.
Цель объекта обещания заключается в том, чтобы предоставить заинтересованным сторонам доступ к результату задачи с отложенным выполнением при ее завершении.
Методы
-
then(successCallback, errorCallback, notifyCallback)— независимо от того, когда обещание было или будет разрешено или отклонено,thenасинхронно вызывает один из обратных вызовов успешного или ошибочного завершения, как только результат станет доступным. Обратные вызовы вызываются с одним аргументом: результатом или причиной отказа. Кроме того, обратный вызов уведомления может быть вызван ноль или более раз для предоставления индикатора прогресса до разрешения или отклонения обещания.Этот метод возвращает новое обещание, которое разрешается или отклоняется через возвращаемое значение
successCallback,errorCallback. Он также уведомляет через возвращаемое значение методаnotifyCallback. Обещание не может быть разрешено или отклонено из метода notifyCallback. -
catch(errorCallback)— сокращенная запись дляpromise.then(null, errorCallback).Поскольку
catchявляется зарезервированным словом в JavaScript, а зарезервированные ключевые слова не поддерживаются в качестве имен свойств ES3, вам необходимо вызвать метод, какpromise['catch'](callback)илиpromise.then(null, errorCallback), чтобы сделать ваш код совместимым с IE8 и Android 2.x. -
finally(callback)— позволяет наблюдать за выполнением или отклонением обещания, но не изменяя конечное значение. Это полезно для освобождения ресурсов или выполнения какой-либо очистки, которая должна выполняться независимо от того, было ли обещание отклонено или разрешено. Подробное описание см. в полном спецификации.Поскольку
finallyявляется зарезервированным словом в JavaScript, и зарезервированные ключевые слова не поддерживаются в качестве имен свойств ES3, вам необходимо вызвать метод так:promise['finally'](callback), чтобы сделать код совместимым с IE8 и Android 2.x.
Цепочки обещаний
Поскольку вызов метода then обещания возвращает новое производное обещание, легко создать цепочку обещаний:
promiseB = promiseA.then(function(result) {
return result + 1;
});
// promiseB will be resolved immediately after promiseA is resolved and its value
// will be the result of promiseA incremented by 1
Можно создавать цепочки любой длины, и поскольку обещание может быть разрешено другим обещанием (что отложит его разрешение дальше), можно приостановить/отложить разрешение обещаний в любой точке цепочки. Это позволяет реализовать мощные API, такие как обработчики ответов $http.
Различия между Q Криса Ковала и $q
Есть два основных отличия:
- $q интегрирован с механизмом наблюдения модели
$rootScope.ScopeScope в Angular, что означает более быстрое распространение разрешения или отклонения в модели и избежание ненужных перерисовок браузера, что приведет к мерцанию интерфейса пользователя. -
Q содержит гораздо больше функций, чем $q, но это влечет за собой увеличение размера. $q очень компактный, но содержит все важные функции, необходимые для общих асинхронных задач.
Тестирование
it('should simulate promise', inject(function($q, $rootScope) { var deferred = $q.defer(); var promise = deferred.promise; var resolvedValue; promise.then(function(value) { resolvedValue = value; }); expect(resolvedValue).toBeUndefined(); // Simulate resolving of promise deferred.resolve(123); // Note that the 'then' function does not get called synchronously. // This is because we want the promise API to always be async, whether or not // it got called synchronously or asynchronously. expect(resolvedValue).toBeUndefined(); // Propagate promise resolution to 'then' functions using $apply(). $rootScope.$apply(); expect(resolvedValue).toEqual(123); }));
Зависимости
Методы
-
defer();
Создает объект
Deferred, который представляет задачу, которая будет завершена в будущем.Возвращает
DeferredВозвращает новый экземпляр отложенного объекта.
-
reject(reason);
Создает обещание, которое разрешается как отклоненное со значением отказа, указанным в
reason. Этот API следует использовать для передачи отказа в цепочке обещаний. Если вы работаете с последним обещанием в цепочке обещаний, вам об этом не нужно беспокоиться.При сравнении отложенных объектов/обещаний с привычным поведением try/catch/throw, считайте
rejectкакthrowключевое слово в JavaScript. Это также означает, что если вы «перехватываете» ошибку через обратный вызов ошибки обещания и хотите передать ошибку обещанию, полученному из текущего обещания, вам нужно «перебросить» ошибку, вернув отказ, созданный с помощьюreject.promiseB = promiseA.then(function(result) { // success: do something and resolve promiseB // with the old or a new result return result; }, function(reason) { // error: handle the error if possible and // resolve promiseB with newPromiseOrValue, // otherwise forward the rejection to promiseB if (canHandle(reason)) { // handle the error and recover return newPromiseOrValue; } return $q.reject(reason); });Параметры
Параметр Тип Подробности reason *Постоянная, сообщение, исключение или объект, представляющий причину отклонения.
Возвращает
PromiseВозвращает обещание, которое уже было разрешено как отклоненное со значением
reason. -
when(value);
Оборачивает объект, который может быть значением или обещанием (третьей стороны), в обещание $q. Это полезно, когда вы имеете дело с объектом, который может или не может быть обещанием, или если обещание поступает из источника, которому нельзя доверять.
Параметры
Параметр Тип Подробности value *Значение или обещание
Возвращает
PromiseВозвращает обещание переданного значения или обещания
-
all(promises);
Объединяет несколько обещаний в одно обещание, которое разрешается, когда все входные обещания разрешены.
Параметры
Параметр Тип Подробности promises Array.<Promise>Object.<Promise>Массив или хеш-таблица обещаний.
Возвращает
PromiseВозвращает одно обещание, которое будет разрешено массивом/хеш-таблицей значений, каждое значение соответствует обещанию в том же индексе/ключе в массиве/хеш-таблице
promises. Если любое из обещаний разрешено с отказом, это результирующее обещание будет отклонено с тем же значением отказа.
© 2010–2017 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://code.angularjs.org/1.2.32/docs/api/ng/service/$q