我按照 Bradley Braithwaite 在他的 博客 中建议的方法来做:
app
.factory('searchService', ['$q', '$http', function($q, $http) {
var service = {};
service.search = function search(query) {
var deferred = $q.defer();
$http
.get('http://localhost/v1?=q' + query)
.success(function(data) {
deferred.resolve(data);
})
.error(function(reason) {
deferred.reject(reason);
});
return deferred.promise;
};
return service;
}])
.controller('SearchController', ['$scope', 'searchService', function($scope, searchService) {
searchService
.search($scope.query)
.then(function(data) {
$scope.results = data;
})
.catch(function(reason) {
$scope.error = 'There has been an error: ' + reason;
});
}])
重点:
resolve函数链接到我们控制器中的.then函数,即一切正常,所以我们可以遵守承诺并解决它。
reject函数链接到我们控制器中的.catch函数,即出现问题,因此我们无法遵守承诺并需要拒绝它。
如果您有其他条件来拒绝承诺,那么在成功函数中过滤数据并使用拒绝原因调用deferred.reject(anotherReason)始终是相当稳定和安全的。
正如Ryan Vice在评论中建议的那样,这可能不会被视为有用,除非您稍微调整一下响应。
由于自1.4版本以来已弃用success和error,因此最好使用常规的promise方法then和catch,并在这些方法中转换响应并返回该转换响应的承诺。
我将展示两种方法和第三种介于两者之间的方法的相同示例。
success
和 error
方法(success
和 error
返回一个 HTTP 响应的 Promise,因此我们需要使用 $q
来返回数据的 Promise):
function search(query) {
var deferred = $q.defer();
$http.get('http://localhost/v1?=q' + query)
.success(function(data,status) {
deferred.resolve(data);
})
.error(function(reason,status) {
if(reason.error){
deferred.reject({text:reason.error, status:status});
}else{
deferred.reject({text:'whatever', status:500});
}
});
return deferred.promise;
};
then
和 catch
方法(由于 throw 的存在,这个测试会稍微有些困难):
function search(query) {
var promise=$http.get('http://localhost/v1?=q' + query)
.then(function (response) {
return response.data;
},function(reason) {
if(reason.statusText){
throw reason;
}else{
throw {statusText:'Call error', status:500};
}
});
return promise;
}
不过,有一个折中的解决方案(这样你就可以避免使用throw
,而且你可能需要在测试中使用$q
来模拟Promise的行为):
function search(query) {
var deferred = $q.defer();
$http.get('http://localhost/v1?=q' + query)
.then(function (response) {
deferred.resolve(response.data);
},function(reason) {
if(reason.statusText){
deferred.reject(reason);
}else{
deferred.reject({statusText:'Call error', status:500});
}
});
return deferred.promise;
}
欢迎任何形式的评论或更正。
catch()
使用success()
、error()
和finally()
,您可以按照以下方式处理:somePromise() .then(successFunction) .catch(errorFunction) .finally(cleanUp)
这将在 Promise 成功后执行successFunction
,如果 Promise 失败,则执行errorFunction
。然后,无论 Promise 成功或失败,都会执行cleanUp
。您还可以使用try-catch
块和async/await
来捕获和处理错误。如果您希望使用then()
,那么您可以使用以下代码:somePromise() .then(successFunction, errorFunction) .then(cleanUp) .catch(exceptionHandling)
这将在 Promise 成功时调用successFunction
,在 Promise 失败时调用errorFunction
,在成功或失败后都会执行cleanUp
。 如果发生异常,则会在catch()
中捕获并进行处理。 - Joelsuccess
和error
(而是更喜欢使用.then
和.catch
),在使用.then
时可以省略errorFunction
,并像我的代码中一样使用catch
。 - Benjamin Gruenbaumsuccess
/error
吗?另外,当 Eclipse 看到.catch(
时,我的 Eclipse 就会失控,所以我现在使用["catch"](
。我该如何驯服 Eclipse? - Giszmo.success
和.error
,$http 返回一个 $q promise 并附加success
和error
处理程序,然而这些处理程序不会链式调用,如果可能的话应该避免使用。通常来说,如果您有疑问,最好将它们作为一个新问题提出,而不是在旧问题的评论中提问。 - Benjamin Gruenbaum