Robię to tak, jak sugeruje Bradley Braithwaite na swoim blogu :
app
.factory('searchService', ['$q', '$http', function($q, $http) {
var service = {};
service.search = function search(query) {
// We make use of Angular's $q library to create the deferred instance
var deferred = $q.defer();
$http
.get('http://localhost/v1?=q' + query)
.success(function(data) {
// The promise is resolved once the HTTP call is successful.
deferred.resolve(data);
})
.error(function(reason) {
// The promise is rejected if there is an error with the HTTP call.
deferred.reject(reason);
});
// The promise is returned to the caller
return deferred.promise;
};
return service;
}])
.controller('SearchController', ['$scope', 'searchService', function($scope, searchService) {
// The search service returns a promise API
searchService
.search($scope.query)
.then(function(data) {
// This is set when the promise is resolved.
$scope.results = data;
})
.catch(function(reason) {
// This is set in the event of an error.
$scope.error = 'There has been an error: ' + reason;
});
}])
Kluczowe punkty:
Funkcja rozwiązywania łączy się z funkcją .then w naszym kontrolerze, czyli wszystko jest w porządku, więc możemy dotrzymać obietnicy i rozwiązać ją.
Funkcja odrzucania łączy się z funkcją .catch w naszym kontrolerze, czyli coś poszło nie tak, więc nie możemy dotrzymać obietnicy i musimy ją odrzucić.
Jest dość stabilny i bezpieczny, a jeśli masz inne warunki, aby odrzucić obietnicę, zawsze możesz filtrować swoje dane w funkcji sukcesu i dzwonić deferred.reject(anotherReason)z przyczyną odrzucenia.
Jak zasugerował Ryan Vice w komentarzach , może to nie być postrzegane jako przydatne, chyba że będziesz trochę bawić się odpowiedzią, że tak powiem.
Ponieważ successi errorsą przestarzałe od wersji 1.4, być może lepiej jest użyć zwykłych metod obietnicy thenicatch i przekształcenia odpowiedzi w tych metodach i powrócić obietnicę tej przekształconej odpowiedzi.
Pokazuję ten sam przykład z obydwoma podejściami i trzecim podejściem pośrednim:
successi errorpodejdź ( successi errorzwróć obietnicę odpowiedzi HTTP, więc potrzebujemy pomocy, $qaby zwrócić obietnicę danych):
function search(query) {
// We make use of Angular's $q library to create the deferred instance
var deferred = $q.defer();
$http.get('http://localhost/v1?=q' + query)
.success(function(data,status) {
// The promise is resolved once the HTTP call is successful.
deferred.resolve(data);
})
.error(function(reason,status) {
// The promise is rejected if there is an error with the HTTP call.
if(reason.error){
deferred.reject({text:reason.error, status:status});
}else{
//if we don't get any answers the proxy/api will probably be down
deferred.reject({text:'whatever', status:500});
}
});
// The promise is returned to the caller
return deferred.promise;
};
theni catchpodejście (jest to trochę trudniejsze do przetestowania ze względu na rzut):
function search(query) {
var promise=$http.get('http://localhost/v1?=q' + query)
.then(function (response) {
// The promise is resolved once the HTTP call is successful.
return response.data;
},function(reason) {
// The promise is rejected if there is an error with the HTTP call.
if(reason.statusText){
throw reason;
}else{
//if we don't get any answers the proxy/api will probably be down
throw {statusText:'Call error', status:500};
}
});
return promise;
}
Istnieje jednak rozwiązanie połowiczne (w ten sposób możesz uniknąć, throwa mimo to prawdopodobnie będziesz musiał użyć, $qaby kpić z obiecującego zachowania w swoich testach):
function search(query) {
// We make use of Angular's $q library to create the deferred instance
var deferred = $q.defer();
$http.get('http://localhost/v1?=q' + query)
.then(function (response) {
// The promise is resolved once the HTTP call is successful.
deferred.resolve(response.data);
},function(reason) {
// The promise is rejected if there is an error with the HTTP call.
if(reason.statusText){
deferred.reject(reason);
}else{
//if we don't get any answers the proxy/api will probably be down
deferred.reject({statusText:'Call error', status:500});
}
});
// The promise is returned to the caller
return deferred.promise;
}
Wszelkie uwagi i poprawki są mile widziane.
success(),error()afinally()w połączeniu zcatch()? Czy też muszę użyćthen(successFunction, errorFunction).catch(exceotionHandling).then(cleanUp);