AngularJS
Kątowe obietnice z usługą $ q
Szukaj…
Używanie $ q.all do obsługi wielu obietnic
Możesz użyć funkcji $q.all
aby wywołać metodę .then
po pomyślnym rozwiązaniu tablicy obietnic i pobraniu danych, które zostały rozwiązane.
Przykład:
JS:
$scope.data = []
$q.all([
$http.get("data.json"),
$http.get("more-data.json"),
]).then(function(responses) {
$scope.data = responses.map((resp) => resp.data);
});
Powyższy kod działa $http.get
2 razy do danych w plikach lokalnych json, gdy zarówno get
metoda zakończyć się rozwiązać związane z nimi obietnice, gdy wszystkie obietnice w tablicy są rozwiązany, .then
rozpoczyna metoda zarówno dane obietnice wewnątrz responses
argument tablicowy.
Dane są następnie mapowane, aby mogły zostać pokazane w szablonie, który możemy następnie pokazać
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"
}]
Używanie konstruktora $ q do tworzenia obietnic
Funkcja konstruktora $q
służy do tworzenia obietnic z asynchronicznych interfejsów API, które używają wywołań zwrotnych do zwracania wyników.
$ q (funkcja (rozwiązuje, odrzuca) {...})
Funkcja konstruktora odbiera funkcję, która jest wywoływana z dwoma argumentami: resolve
i reject
które są funkcjami używanymi do rozwiązania lub odrzucenia obietnicy.
Przykład 1:
function $timeout(fn, delay) {
return = $q(function(resolve, reject) {
setTimeout(function() {
try {
let r = fn();
resolve(r);
}
catch (e) {
reject(e);
}
}, delay);
};
}
Powyższy przykład tworzy obietnicę z interfejsu API WindowTimers.setTimeout . Struktura AngularJS zapewnia bardziej rozbudowaną wersję tej funkcji. Informacje na temat użytkowania można znaleźć w dokumentacji interfejsu API usługi limitu czasu usługi AngularJS $ .
Przykład 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);
}
});
}
Powyższy kod pokazuje obiecaną funkcję podziału, zwróci obietnicę z wynikiem lub odrzuci powód, jeśli obliczenie jest niemożliwe.
Można połączyć i wykorzystać .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.
})
Odroczenie operacji za pomocą $ q.defer
Możemy użyć $q
aby odroczyć operacje na przyszłość, mając obecnie oczekujący obiekt przyrzeczenia, używając $q.defer
tworzymy obietnicę, która zostanie rozwiązana lub odrzucona w przyszłości.
Ta metoda nie jest równoważna z użyciem konstruktora $q
, ponieważ używamy $q.defer
aby obiecać istniejącą procedurę, która może, ale nie musi, w ogóle (lub kiedykolwiek zwróciła) obietnicę.
Przykład:
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) {})
Pamiętaj, aby zawsze zwracać obiekt
deferred.promise
lub ryzykować błąd podczas wywoływania..then
Upewnij się, że zawsze rozwiązujesz lub odrzucasz odroczony obiekt, w przeciwnym
.then
może nie działać i ryzykujesz wyciekiem pamięci
Korzystanie z obietnic kątowych w usłudze $ q
$q
jest wbudowaną usługą, która pomaga w wykonywaniu funkcji asynchronicznych i używaniu ich wartości zwracanych (lub wyjątków) po zakończeniu przetwarzania.
$q
jest zintegrowany z mechanizmem obserwacji modelu $rootScope.Scope
, co oznacza szybsze propagowanie rozdzielczości lub odrzucania do twoich modeli i unikanie niepotrzebnych odświeżeń przeglądarki, co spowodowałoby migotanie interfejsu użytkownika.
W naszym przykładzie nazywamy naszą fabrykę getMyData
, która zwraca obiekt obietnicy. Jeśli obiekt zostanie resolved
, zwraca liczbę losową. Jeśli zostanie rejected
, zwraca odrzucenie z komunikatem o błędzie po 2 sekundach.
W fabryce Angular
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;
}
}
Korzystanie z obietnic na telefon
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())
})
})
Aby użyć obietnic, wstrzyknij $q
jako zależność. Tutaj wstrzyknęliśmy $q
do fabryki getMyData
.
var defer = $q.defer();
Nowa instancja odroczenia jest budowana przez wywołanie $q.defer()
Odroczony obiekt to po prostu obiekt, który ujawnia obietnicę, a także powiązane metody jej rozwiązania. Jest skonstruowany przy użyciu funkcji $q.deferred()
i udostępnia trzy główne metody: $q.deferred()
resolve()
, reject()
i notify()
.
-
resolve(value)
- rozwiązuje obietnicę pochodną o wartości. -
reject(reason)
- odrzuca obietnicę pochodną wraz z powodem. -
notify(value)
- informuje o stanie realizacji promesy. Można to wywołać wiele razy, zanim obietnica zostanie rozwiązana lub odrzucona.
Nieruchomości
Powiązany obiekt przyrzeczenia jest dostępny za pośrednictwem właściwości przyrzeczenia. promise
- {Obietnica} - obiekt obietnicy związany z tym odroczeniem.
Nowa instancja obietnicy jest tworzona, gdy tworzona jest odroczona instancja, i można ją odzyskać, wywołując deferred.promise
.
Celem przedmiotu promise
jest umożliwienie zainteresowanym stronom dostępu do wyniku odroczonego zadania po jego zakończeniu.
Metody obietnicy -
then(successCallback, [errorCallback], [notifyCallback])
- Niezależnie od tego, kiedy obietnica została lub zostanie rozwiązana lub odrzucona, wówczas asynchronicznie wywołuje jedno z callbacków powodzenia lub błędu, gdy tylko wynik będzie dostępny. Wywołania zwrotne są wywoływane za pomocą jednego argumentu: wyniku lub powodu odrzucenia. Ponadto powiadomienie zwrotne może być wywoływane zero lub więcej razy, aby zapewnić wskazanie postępu, zanim obietnica zostanie rozpatrzona lub odrzucona.catch(errorCallback)
- skrót dla promise.then (null, errorCallback)finally(callback, notifyCallback)
- pozwala zaobserwować spełnienie lub odrzucenie obietnicy, ale zrobić to bez zmiany ostatecznej wartości.
Jedną z najpotężniejszych cech obietnic jest możliwość ich połączenia. Umożliwia to przepływ danych przez łańcuch oraz manipulowanie i mutowanie na każdym etapie. Pokazano to na następującym przykładzie:
Przykład 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);
});
Zawiń prostą wartość w obietnicę za pomocą $ q.when ()
Jeśli wszystko, czego potrzebujesz, to zawrzeć wartość w obietnicy, nie musisz używać długiej składni, jak tutaj:
//OVERLY VERBOSE
var defer;
defer = $q.defer();
defer.resolve(['one', 'two']);
return defer.promise;
W takim przypadku możesz po prostu napisać:
//BETTER
return $q.when(['one', 'two']);
$ q.when i jego alias $ q.resolve
Zawija obiekt, który może być wartością lub obietnicą (innej firmy), wówczas w obietnicę $ q. Jest to przydatne, gdy masz do czynienia z przedmiotem, który może, ale nie musi być obietnicą, lub jeśli obietnica pochodzi ze źródła, któremu nie można ufać.
- AngularJS $ q Dokumentacja interfejsu API usługi - $ q. Kiedy
Wraz z wydaniem AngularJS v1.4.1
Możesz także użyć resolve
aliasu zgodnego z ES6
//ABSOLUTELY THE SAME AS when
return $q.resolve(['one', 'two'])
Unikaj odroczonego anty-wzoru $ q
Unikaj tego Anti-Pattern
var myDeferred = $q.defer(); $http(config).then(function(res) { myDeferred.resolve(res); }, function(error) { myDeferred.reject(error); }); return myDeferred.promise;
Nie trzeba $q.defer
obietnicy za pomocą $q.defer
ponieważ usługa $ http już zwraca obietnicę.
//INSTEAD
return $http(config);
Po prostu zwróć obietnicę utworzoną przez usługę $ http.