AngularJS
Vinkelföretag med $ q-tjänst
Sök…
Använda $ q.all för att hantera flera löften
Du kan använda $q.all
funktionen för att anropa en .then
efter att en rad löften har lyckats och hämtas de data som de löst med.
Exempel:
JS:
$scope.data = []
$q.all([
$http.get("data.json"),
$http.get("more-data.json"),
]).then(function(responses) {
$scope.data = responses.map((resp) => resp.data);
});
Ovanstående kod kör $http.get
2 gånger för data i lokala json-filer, när båda get
metoden slutförd löser de sina tillhörande löften, när alla löften i matrisen är löst, så .then
metoden med båda löften data inuti responses
array argument.
Data mappas sedan så att de kan visas på mallen, vi kan sedan visa
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"
}]
Använd $ q-konstruktören för att skapa löften
Konstruktorfunktionen $q
används för att skapa löften från asynkrona API: er som använder återuppringningar för att returnera resultat.
$ q (funktion (lösa, avvisa) {...})
Konstruktorfunktionen får en funktion som åberopas med två argument, resolve
och reject
som är funktioner som används för att antingen lösa eller avvisa löfte.
Exempel 1:
function $timeout(fn, delay) {
return = $q(function(resolve, reject) {
setTimeout(function() {
try {
let r = fn();
resolve(r);
}
catch (e) {
reject(e);
}
}, delay);
};
}
Exemplet ovan skapar ett löfte från WindowTimers.setTimeout API . AngularJS-ramverket ger en mer detaljerad version av denna funktion. För användning, se AngularJS $ timeout Service API Reference .
Exempel 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);
}
});
}
Ovanstående kod som visar en lovad delningsfunktion, den kommer att returnera ett löfte med resultatet eller avvisa med en anledning om beräkningen är omöjlig.
Du kan sedan ringa och använda .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.
})
Uppskjutande verksamhet med $ q.defer
Vi kan använda $q
att skjuta upp operationer till framtiden medan vi har ett pågående löfteobjekt för närvarande, genom att använda $q.defer
skapar vi ett löfte som antingen kommer att lösa eller avvisa i framtiden.
Den här metoden är inte likvärdigt med att använda $q
konstruktören, eftersom vi använder $q.defer
att lova en befintlig rutin som kanske eller kanske inte returnerar (eller någonsin hade returnerat) ett löfte alls.
Exempel:
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) {})
Se till att du alltid returnerar ett det
deferred.promise
objektet eller riskerar ett fel när du åberopar.then
Se till att du alltid löser eller avvisar ditt uppskjutna objekt eller.
.then
kanske inte körs och att du riskerar att minnet läcker
Använda vinkellöften med $ q-tjänst
$q
är en inbyggd tjänst som hjälper till att köra asynkronfunktioner och använda deras returvärden (eller undantag) när de är klara med bearbetningen.
$q
är integrerad med $rootScope.Scope
, vilket innebär snabbare spridning av upplösning eller avslag till dina modeller och undviker onödiga webbläsaråtervinningar, vilket skulle resultera i flimrande UI.
I vårt exempel kallar vi vår fabrik getMyData
, som returnerar ett löfteobjekt. Om objektet är resolved
returnerar det ett slumpmässigt nummer. Om det rejected
returnerar det ett avslag med ett felmeddelande efter 2 sekunder.
I vinkelfabrik
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;
}
}
Använda löften vid samtal
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())
})
})
För att använda löften, injicera $q
som beroende. Här injicerade vi $q
i getMyData
fabriken.
var defer = $q.defer();
En ny instans av uppskjuten konstrueras genom att ringa $q.defer()
Ett uppskjutet objekt är helt enkelt ett objekt som avslöjar ett löfte såväl som de tillhörande metoderna för att lösa detta löfte. Den är konstruerad med $q.deferred()
och visar tre huvudmetoder: resolve()
, reject()
och notify()
.
-
resolve(value)
- löser det härledda löfte med värdet. -
reject(reason)
- avvisar det härledda löfte med anledningen. -
notify(value)
- ger uppdateringar om status för löftets genomförande. Detta kan kallas flera gånger innan löften antingen löses eller avvisas.
Egenskaper
Det tillhörande löfteobjektet nås via löfteegenskapen. promise
- {Löfte} - löfteobjekt associerat med denna uppskjutna.
En ny löfteinstans skapas när en uppskjuten instans skapas och kan hämtas genom att ringa deferred.promise
.
Syftet med promise
är att låta intresserade parter få tillgång till resultatet av den uppskjutna uppgiften när den är klar.
Löftsmetoder -
then(successCallback, [errorCallback], [notifyCallback])
- Oavsett när löftet var eller kommer att lösas eller avvisas, ring sedan en av framgångs- eller feluppringningarna asynkront så snart resultatet är tillgängligt. Återuppringningarna kallas med ett enda argument: resultatet eller avvisningsorsaken. Dessutom kan anmälan återuppringning kallas noll eller flera gånger för att ge en statusindikering, innan löften löses eller avvisas.catch(errorCallback)
- kortfattad för lover.then (null, errorCallback)finally(callback, notifyCallback)
- gör att du kan observera antingen uppfyllandet eller avslaget av ett löfte, men att göra det utan att ändra det slutliga värdet.
En av de mest kraftfulla funktionerna i löften är förmågan att kedja dem ihop. Detta gör att data flyter genom kedjan och manipuleras och muteras vid varje steg. Detta demonstreras med följande exempel:
Exempel 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);
});
Förpacka enkelt värde i ett löfte med $ q.when ()
Om allt du behöver är att förpacka värdet till ett löfte behöver du inte använda den långa syntaxen som här:
//OVERLY VERBOSE
var defer;
defer = $q.defer();
defer.resolve(['one', 'two']);
return defer.promise;
I det här fallet kan du bara skriva:
//BETTER
return $q.when(['one', 'two']);
$ q.when och dess alias $ q.resolve
Slår in ett objekt som kan vara ett värde eller ett (tredje part) då-löfte till ett löfte om $ q. Detta är användbart när du har att göra med ett objekt som kanske eller inte kan vara ett löfte, eller om löfte kommer från en källa som inte kan lita på.
Med utgåvan av AngularJS v1.4.1
Du kan också använda en ES6-konsekvent resolve
//ABSOLUTELY THE SAME AS when
return $q.resolve(['one', 'two'])
Undvik $ Q Uppskjuten antimönster
Undvik detta antimönster
var myDeferred = $q.defer(); $http(config).then(function(res) { myDeferred.resolve(res); }, function(error) { myDeferred.reject(error); }); return myDeferred.promise;
Det finns inget behov av att tillverka ett löfte med $q.defer
eftersom tjänsten $ http redan ger ett löfte.
//INSTEAD
return $http(config);
Ge bara det löfte som skapats av tjänsten $ http.