Я делаю это, как предлагает Брэдли Брейтуэйт в своем блоге :
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;
});
}])
Ключевые моменты:
Функция разрешения связана с функцией .then в нашем контроллере, т.е. все в порядке, поэтому мы можем сдержать свое обещание и разрешить его.
Функция reject ссылается на функцию .catch в нашем контроллере, т.е. что-то пошло не так, поэтому мы не можем сдержать свое обещание и должны его отклонить.
Это довольно стабильно и безопасно, и если у вас есть другие условия для отклонения обещания, вы всегда можете отфильтровать свои данные в функции успеха и вызвать deferred.reject(anotherReason)
причину отказа.
Как предположил Райан Вайс в комментариях , это может оказаться бесполезным, если вы, так сказать, немного не поиграете с ответом.
Поскольку success
и error
устарели с версии 1.4, возможно, лучше использовать обычные методы обещаний then
иcatch
и преобразовать ответ в этих методах и вернуть обещание этого трансформированного ответа.
Я показываю один и тот же пример с обоими подходами и третьим промежуточным подходом:
success
и error
подход ( success
и error
вернуть обещание ответа HTTP, поэтому нам нужна помощь $q
для возврата обещания данных):
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;
};
then
и catch
подход (это немного сложнее проверить из-за выброса):
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;
}
Однако есть половинчатое решение (таким образом вы можете избежать throw
и в любом случае вам, вероятно, придется использовать $q
для имитации поведения обещания в ваших тестах):
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;
}
Любые комментарии и исправления приветствуются.
success()
,error()
и вfinally()
сочетании сcatch()
? Или мне нужно использоватьthen(successFunction, errorFunction).catch(exceotionHandling).then(cleanUp);