AngularJS
Угловые обещания с услугой $ q
Поиск…
Использование $ q.all для обработки нескольких обещаний
Вы можете использовать функцию $q.all
для вызова метода .then
после успешного решения массива обещаний и получения данных, с которыми они разрешили.
Пример:
JS:
$scope.data = []
$q.all([
$http.get("data.json"),
$http.get("more-data.json"),
]).then(function(responses) {
$scope.data = responses.map((resp) => resp.data);
});
Вышеприведенный код запускает $http.get
2 раза для данных в локальных json-файлах, когда оба метода get
завершают, они разрешают связанные с ними обещания, когда все обещания в массиве разрешаются, метод .then
начинается с обеим обеим данным в responses
аргумент массива.
Затем данные отображаются таким образом, чтобы их можно было отобразить на шаблоне, затем мы можем показать
HTML:
<ul>
<li ng-repeat="d in data">
<ul>
<li ng-repeat="item in d">{{item.name}}: {{item.occupation}}</li>
</ul>
</li>
</ul>
JSON:
[{
"name": "alice",
"occupation": "manager"
}, {
"name": "bob",
"occupation": "developer"
}]
Использование конструктора $ q для создания обещаний
Функция конструктора $q
используется для создания обещаний от асинхронных API, которые используют обратные вызовы для возврата результатов.
$ q (функция (разрешение, отклонение) {...})
Функция-конструктор получает функцию, которая вызывается с двумя аргументами, resolve
и reject
которые являются функциями, которые используются для разрешения или отклонения обещания.
Пример 1:
function $timeout(fn, delay) {
return = $q(function(resolve, reject) {
setTimeout(function() {
try {
let r = fn();
resolve(r);
}
catch (e) {
reject(e);
}
}, delay);
};
}
В приведенном выше примере создается обещание API WindowTimers.setTimeout . Рамка AngularJS обеспечивает более сложную версию этой функции. Для использования см. Справочную информацию об API-интерфейсе AngularJS $ .
Пример 2:
$scope.divide = function(a, b) {
return $q(function(resolve, reject) {
if (b===0) {
return reject("Cannot devide by 0")
} else {
return resolve(a/b);
}
});
}
Вышеприведенный код, демонстрирующий функцию обобщенного деления, возвращает обещание с результатом или отклонение по причине, если расчет невозможно.
Затем вы можете позвонить и использовать. .then
$scope.divide(7, 2).then(function(result) {
// will return 3.5
}, function(err) {
// will not run
})
$scope.divide(2, 0).then(function(result) {
// will not run as the calculation will fail on a divide by 0
}, function(err) {
// will return the error string.
})
Операции отсрочки с использованием $ q.defer
Мы можем использовать $q
для отсрочки операций в будущем, имея в настоящее время ожидающий объект обещания, используя $q.defer
мы создаем обещание, которое будет либо разрешаться, либо отклоняться в будущем.
Этот метод не эквивалентен использованию конструктора $q
, так как мы используем $q.defer
чтобы обещать существующую процедуру, которая может или не может возвращать (или когда-либо возвращал) обещание вообще.
Пример:
var runAnimation = function(animation, duration) {
var deferred = $q.defer();
try {
...
// run some animation for a given duration
deferred.resolve("done");
} catch (err) {
// in case of error we would want to run the error hander of .then
deferred.reject(err);
}
return deferred.promise;
}
// and then
runAnimation.then(function(status) {}, function(error) {})
Убедитесь, что вы всегда возвращаете объект
deferred.promise
Или можете.then
при вызове..then
Убедитесь , что вы всегда разрешить или отклонить отложенный объект или
.then
не может работать , и вы рискуете утечку памяти
Использование угловых обещаний с помощью услуги $ q
$q
- это встроенный сервис, который помогает выполнять асинхронные функции и использовать их возвращаемые значения (или исключение), когда они закончены с обработкой.
$q
интегрируется с механизмом наблюдения за моделью $rootScope.Scope
, что означает более быстрое распространение разрешения или отклонения в ваших моделях и исключение ненужных переходов браузера, что приведет к мерцанию пользовательского интерфейса.
В нашем примере мы называем наш завод getMyData
, который возвращает объект обещания. Если объект resolved
, он возвращает случайное число. Если он rejected
, он возвращает отказ с сообщением об ошибке через 2 секунды.
В Угловом заводе
function getMyData($timeout, $q) {
return function() {
// simulated async function
var promise = $timeout(function() {
if(Math.round(Math.random())) {
return 'data received!'
} else {
return $q.reject('oh no an error! try again')
}
}, 2000);
return promise;
}
}
Использование обещаний по вызову
angular.module('app', [])
.factory('getMyData', getMyData)
.run(function(getData) {
var promise = getData()
.then(function(string) {
console.log(string)
}, function(error) {
console.error(error)
})
.finally(function() {
console.log('Finished at:', new Date())
})
})
Чтобы использовать обещания, введите $q
качестве зависимости. Здесь мы вводили $q
в фабрику getMyData
.
var defer = $q.defer();
Новый экземпляр отложенных построен путем вызова $q.defer()
Отложенный объект - это просто объект, который предоставляет обещание, а также связанные с ним методы для решения этого обещания. Он построен с использованием функции $q.deferred()
и предоставляет три основных метода: resolve()
, reject()
и notify()
.
-
resolve(value)
- разрешает производное обещание со значением. -
reject(reason)
- отклоняет полученное обещание по причине. -
notify(value)
- предоставляет обновления статуса выполнения обещания. Это можно назвать несколько раз до того, как обещание будет разрешено или отклонено.
свойства
Связанный объект обещания доступен через свойство prom. promise
- {Обещание} - объект обещания, связанный с этим отсроченным.
Новый экземпляр обещания создается, когда созданный отложенный экземпляр создается и может быть получен путем вызова deferred.promise
.
Цель объекта promise
- предоставить заинтересованным сторонам возможность получить доступ к результатам отложенной задачи, когда она будет завершена.
Методы обещания -
then(successCallback, [errorCallback], [notifyCallback])
Независимо от того, когда обещание было или будет разрешено или отклонено, он вызывает асинхронный вызов одного из успешных или ошибочных обратных вызовов, как только результат будет доступен. Обратные вызовы вызываются с помощью одного аргумента: причина или отклонение. Кроме того, обратный вызов уведомления может быть вызван ноль или более раз, чтобы обеспечить индикацию выполнения, прежде чем обещание будет разрешено или отклонено.catch(errorCallback)
- сокращенноеcatch(errorCallback)
для обещания. then (null, errorCallback)finally(callback, notifyCallback)
- позволяет вам наблюдать за выполнением или отказом от обещания, но делать это без изменения окончательного значения.
Одной из самых мощных возможностей обещаний является способность объединить их вместе. Это позволяет данным проходить через цепочку и манипулировать и мутировать на каждом шаге. Это продемонстрировано в следующем примере:
Пример 1:
// Creates a promise that when resolved, returns 4.
function getNumbers() {
var promise = $timeout(function() {
return 4;
}, 1000);
return promise;
}
// Resolve getNumbers() and chain subsequent then() calls to decrement
// initial number from 4 to 0 and then output a string.
getNumbers()
.then(function(num) {
// 4
console.log(num);
return --num;
})
.then(function (num) {
// 3
console.log(num);
return --num;
})
.then(function (num) {
// 2
console.log(num);
return --num;
})
.then(function (num) {
// 1
console.log(num);
return --num;
})
.then(function (num) {
// 0
console.log(num);
return 'And we are done!';
})
.then(function (text) {
// "And we are done!"
console.log(text);
});
Оберните простое значение в обещание, используя $ q.when ()
Если все, что вам нужно, это превратить ценность в обещание, вам не нужно использовать длинный синтаксис, как здесь:
//OVERLY VERBOSE
var defer;
defer = $q.defer();
defer.resolve(['one', 'two']);
return defer.promise;
В этом случае вы можете просто написать:
//BETTER
return $q.when(['one', 'two']);
$ q.when и его псевдоним $ q.resolve
Обертывает объект, который может быть значением или (сторонним), а затем - обещанием в обещание в $ q. Это полезно, когда вы имеете дело с объектом, который может или не может быть обещанием, или если обещание исходит от источника, которому нельзя доверять.
С выпуском AngularJS v1.4.1
Вы можете также использовать ES6-последовательный псевдоним resolve
//ABSOLUTELY THE SAME AS when
return $q.resolve(['one', 'two'])
Избегайте $ q отложенного анти-шаблона
Избегайте этого Anti-Pattern
var myDeferred = $q.defer(); $http(config).then(function(res) { myDeferred.resolve(res); }, function(error) { myDeferred.reject(error); }); return myDeferred.promise;
Нет необходимости $q.defer
обещание с помощью $q.defer
поскольку служба $ http уже возвращает обещание.
//INSTEAD
return $http(config);
Просто верните обещание, созданное службой $ http.