AngularJS
Promesse angolari con servizio $ q
Ricerca…
Usando $ q.tutti per gestire più promesse
È possibile utilizzare la funzione $q.all
per chiamare un metodo .then
dopo che una serie di promesse è stata risolta correttamente e recuperare i dati risolti.
Esempio:
JS:
$scope.data = []
$q.all([
$http.get("data.json"),
$http.get("more-data.json"),
]).then(function(responses) {
$scope.data = responses.map((resp) => resp.data);
});
Il codice precedente esegue $http.get
2 volte per i dati nei file json locali, quando entrambi get
metodo completato risolvono le promesse associate, quando tutte le promesse nell'array vengono risolte, il metodo .then
inizia con entrambi i dati promessi all'interno delle responses
argomento dell'array.
I dati vengono quindi mappati in modo che possano essere visualizzati sul modello, quindi possiamo mostrarli
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"
}]
Usare il costruttore $ q per creare promesse
La funzione costruttore $q
viene utilizzata per creare promesse da API asincrone che utilizzano callback per restituire risultati.
$ q (funzione (risoluzione, rifiuto) {...})
La funzione di costruzione riceve una funzione invocata con due argomenti, resolve
e reject
che sono funzioni utilizzate per risolvere o rifiutare la promessa.
Esempio 1:
function $timeout(fn, delay) {
return = $q(function(resolve, reject) {
setTimeout(function() {
try {
let r = fn();
resolve(r);
}
catch (e) {
reject(e);
}
}, delay);
};
}
L'esempio precedente crea una promessa dall'API WindowTimers.setTimeout . Il framework AngularJS fornisce una versione più elaborata di questa funzione. Per l'utilizzo, consultare il riferimento all'API del servizio Timeout di AngularJS $ .
Esempio 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);
}
});
}
Il codice precedente che mostra una funzione di divisione promessa, restituirà una promessa con il risultato o rifiuta con un motivo se il calcolo è impossibile.
È quindi possibile chiamare e utilizzare. .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.
})
Differire le operazioni usando $ q.defer
Possiamo usare $q
per posticipare le operazioni al futuro mentre al momento abbiamo un oggetto promessa in sospeso, usando $q.defer
creiamo una promessa che sarà risolta o respinta in futuro.
Questo metodo non è equivalente all'uso del costruttore $q
, poiché usiamo $q.defer
per promettere una routine esistente che può o non può restituire (o che ha mai restituito) una promessa.
Esempio:
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) {})
Assicurati di restituire sempre un oggetto
deferred.promise
o rischiare un errore durante il.then
Assicurati di risolvere o rifiutare sempre il tuo oggetto posticipato o
.then
non funzionare e rischi una perdita di memoria
Usando promesse angolari con $ q servizio
$q
è un servizio integrato che aiuta nell'esecuzione di funzioni asincrone e utilizza i loro valori di ritorno (o eccezioni) al termine dell'elaborazione.
$q
è integrato con il meccanismo di osservazione del modello $rootScope.Scope
, che significa propagazione più rapida della risoluzione o del rifiuto nei modelli ed evita inutili ridondazioni del browser, il che comporterebbe un'interfaccia utente tremolante.
Nel nostro esempio, chiamiamo la nostra factory getMyData
, che restituisce un oggetto promessa. Se l'oggetto è resolved
, restituisce un numero casuale. Se viene rejected
, restituisce un rifiuto con un messaggio di errore dopo 2 secondi.
In fabbrica angolare
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;
}
}
Utilizzo di promesse in chiamata
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())
})
})
Per usare le promesse, iniettare $q
come dipendenza. Qui abbiamo iniettato $q
nella fabbrica getMyData
.
var defer = $q.defer();
Viene $q.defer()
una nuova istanza di differita chiamando $q.defer()
Un oggetto differito è semplicemente un oggetto che espone una promessa così come i metodi associati per risolvere quella promessa. È costruito usando la funzione $q.deferred()
ed espone tre metodi principali: resolve()
, reject()
e notify()
.
-
resolve(value)
- risolve la promessa derivata con il valore. -
reject(reason)
- respinge la promessa derivata con la ragione. -
notify(value)
: fornisce aggiornamenti sullo stato dell'esecuzione della promessa. Questo può essere chiamato più volte prima che la promessa sia risolta o respinta.
Proprietà
L'oggetto promessa associato è accessibile tramite la proprietà promessa. promise
- {Promise} - promessa oggetto associato a questo rinviato.
Una nuova istanza di promessa viene creata quando viene creata un'istanza posticipata e può essere recuperata chiamando deferred.promise
.
Lo scopo dell'oggetto promise
è quello di consentire alle parti interessate di ottenere l'accesso al risultato dell'attività differita al suo completamento.
Metodi promettenti -
then(successCallback, [errorCallback], [notifyCallback])
- Indipendentemente da quando la promessa è stata o sarà risolta o rifiutata, quindi chiama uno dei callback di successo o di errore in modo asincrono non appena il risultato è disponibile. I callback vengono chiamati con un singolo argomento: il motivo del risultato o del rifiuto. Inoltre, il callback di notifica può essere chiamato zero o più volte per fornire un'indicazione di avanzamento, prima che la promessa sia risolta o respinta.catch(errorCallback)
- abbreviazione di promise.then (null, errorCallback)finally(callback, notifyCallback)
- consente di osservare l'adempimento o il rifiuto di una promessa, ma di farlo senza modificare il valore finale.
Una delle caratteristiche più potenti delle promesse è la capacità di concatenarle. Ciò consente ai dati di fluire attraverso la catena e di essere manipolati e mutati ad ogni passaggio. Questo è dimostrato con il seguente esempio:
Esempio 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);
});
Inserisci un valore semplice in una promessa utilizzando $ q.when ()
Se tutto ciò che serve è racchiudere il valore in una promessa, non è necessario utilizzare la sintassi lunga come qui:
//OVERLY VERBOSE
var defer;
defer = $q.defer();
defer.resolve(['one', 'two']);
return defer.promise;
In questo caso puoi scrivere:
//BETTER
return $q.when(['one', 'two']);
$ q.quando e il suo alias $ q.resolve
Avvolge un oggetto che potrebbe essere un valore o una promessa in grado (di terze parti) in una promessa di $ q. Ciò è utile quando hai a che fare con un oggetto che potrebbe o non potrebbe essere una promessa, o se la promessa proviene da una fonte che non può essere considerata attendibile.
Con il rilascio di AngularJS v1.4.1
Puoi anche utilizzare una resolve
alias coerente con ES6
//ABSOLUTELY THE SAME AS when
return $q.resolve(['one', 'two'])
Evita l'anti-pattern rinviato $ q
Evita questo anti-pattern
var myDeferred = $q.defer(); $http(config).then(function(res) { myDeferred.resolve(res); }, function(error) { myDeferred.reject(error); }); return myDeferred.promise;
Non è necessario produrre una promessa con $q.defer
poiché il servizio $ http restituisce già una promessa.
//INSTEAD
return $http(config);
È sufficiente restituire la promessa creata dal servizio $ http.