Улучшить эту документацию Просмотреть исходный код $q
- $qProvider
- сервис в модуле ng
Обзор
Сервис, который помогает выполнять асинхронные функции и использовать их возвращаемые значения (или исключения) по завершении обработки.
Это реализация обещаний/объектов отложенного выполнения, совместимая со спецификацией Promises/A+, вдохновленная реализацией Kris Kowal's Q.
$q может использоваться двумя способами — один более похож на реализацию Kris Kowal's Q или jQuery's Deferred, а другой в некоторой степени напоминает обещания ES6 (ES2015).
$q конструктор
Упрощённое обещание в стиле ES6 фактически использует $q как конструктор, принимающий resolver функцию в качестве первого аргумента. Это аналогично реализации Promise из ES6, см. MDN.
Хотя использование конструктора поддерживается, не все поддерживающие методы обещаний ES6 доступны пока.
Можно использовать его так:
// for the purpose of this example let's assume that variables `$q` and `okToGreet`
// are available in the current lexical scope (they could have been injected or passed in).
function asyncGreet(name) {
// perform some asynchronous operation, resolve or reject the promise when appropriate.
return $q(function(resolve, reject) {
setTimeout(function() {
if (okToGreet(name)) {
resolve('Hello, ' + name + '!');
} else {
reject('Greeting ' + name + ' is not allowed.');
}
}, 1000);
});
}
var promise = asyncGreet('Robin Hood');
promise.then(function(greeting) {
alert('Success: ' + greeting);
}, function(reason) {
alert('Failed: ' + reason);
});
Примечание: обработчики progress/notify в настоящее время не поддерживаются через интерфейс в стиле ES6.
Примечание: в отличие от поведения ES6, исключение, сгенерированное в функции конструктора, НЕ подразумевает отказ от выполнения обещания.
Однако более традиционное использование в стиле CommonJS по-прежнему доступно и документировано ниже.
Предложение CommonJS по обещаниям описывает обещание как интерфейс для взаимодействия с объектом, представляющим результат асинхронного действия, которое может или не может быть завершено в любой момент времени.
С точки зрения обработки ошибок, API отложенного выполнения и обещаний относятся к асинхронному программированию так же, как try, catch и throw ключевые слова относятся к синхронному программированию.
// for the purpose of this example let's assume that variables `$q` 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. Аргументы errorCallback и notifyCallback необязательны. -
catch(errorCallback)— сокращение дляpromise.then(null, errorCallback) -
finally(callback, notifyCallback)— позволяет наблюдать за выполнением или отказом обещания, но не изменяя конечное значение. Это полезно для освобождения ресурсов или выполнения какой-либо очистки, которая должна быть выполнена, независимо от того, было ли обещание отклонено или разрешено. Для получения дополнительной информации см. полную спецификацию.
Цепочки обещаний
Поскольку вызов метода 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 от Kris Kowal и $q
Существуют два основных отличия:
- $q интегрирован с механизмом наблюдения модели
$rootScope.ScopeScope в AngularJS, что означает более быстрое распространение разрешения или отклонения в ваши модели и избежание ненужных перерисовки браузера, что привело бы к мерцанию интерфейса. - 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);
}));
Зависимости
Использование
$q(resolver);
Аргументы
| Параметр | Тип | Подробности |
|---|---|---|
| resolver | function(function, function) | Функция, ответственная за разрешение или отклонение вновь созданного промиса. Первый параметр — функция разрешения промиса, второй — функция отклонения промиса. |
Возвращаемое значение
Promise |
Новый созданный промис. |
Методы
-
defer();
Создаёт объект
Deferred, представляющий задачу, которая завершится в будущем.Возвращаемое значение
DeferredВозвращает новый экземпляр объекта deferred.
-
reject(reason);
Создаёт промис, который отклоняется со значением
reason. Данный API следует использовать для передачи отклонения в цепочке промисов. Если вы работаете с последним промисом в цепочке, беспокоиться не нужно.Сравнивая deferred/промисы с привычным поведением 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, [successCallback], [errorCallback], [progressCallback]);
Оборачивает объект, который может быть значением или (третьим) then-able промисом, в промис $q. Это полезно, когда вы работаете с объектом, который может или не может быть промисом, или если промис получен из источника, которому нельзя доверять.
Параметры
Параметр Тип Подробности value *Значение или промис
successCallback (необязательно)Function=errorCallback (необязательно)Function=progressCallback (необязательно)Function=Возвращаемое значение
PromiseВозвращает промис переданного значения или промиса
-
resolve(value, [successCallback], [errorCallback], [progressCallback]);
Псевдоним для when для сохранения согласованности именования с ES6.
Параметры
Параметр Тип Подробности value *Значение или промис
successCallback (необязательно)Function=errorCallback (необязательно)Function=progressCallback (необязательно)Function=Возвращаемое значение
PromiseВозвращает промис переданного значения или промиса
-
all(promises);
Объединяет несколько промисов в один промис, который разрешается, когда все входные промисы разрешаются.
Параметры
Параметр Тип Подробности promises Array.<Promise>Object.<Promise>Массив или хеш промисов.
Возвращаемое значение
PromiseВозвращает один промис, который будет разрешён массивом/хешем значений, каждое значение соответствует промису с тем же индексом/ключом в массиве/хеше
promises. Если любой из промисов отклоняется, этот результирующий промис будет отклонен с тем же значением отклонения. -
race(promises);
Возвращает промис, который разрешается или отклоняется, как только один из промисов разрешается или отклоняется, со значением или причиной от того промиса.
Параметры
Параметр Тип Подробности promises Array.<Promise>Object.<Promise>Массив или хеш промисов.
Возвращаемое значение
Promiseпромис, который разрешается или отклоняется, как только один из
promisesразрешается или отклоняется, со значением или причиной от того промиса.
© 2010–2020 Google, Inc.
Licensed under the Creative Commons Attribution License 3.0.
https://code.angularjs.org/1.8.2/docs/api/ng/service/$q