在 AngularJS 中使用成功/错误/最终/捕获和承诺

我正在 AngularJs 中使用 $http,我不确定如何使用返回的承诺和处理错误。

I have this code:

$http
.get(url)
.success(function(data) {
// Handle data
})
.error(function(data, status) {
// Handle HTTP error
})
.finally(function() {
// Execute logic independent of success/error
})
.catch(function(error) {
// Catch and handle exceptions from success/error/finally functions
});

这是个好办法,还是有更简单的办法?

213538 次浏览

你想要什么样的粒度? 你通常可以用:

$http.get(url).then(
//success function
function(results) {
//do something w/results.data
},
//error function
function(err) {
//handle error
}
);

我发现“ finally”和“ catch”在连接多个承诺时效果更好。

承诺是对语句的抽象,允许我们用异步代码同步地表达自己。它们表示一次性任务的执行。

它们还提供异常处理,就像普通代码一样,您可以从承诺返回或者引发。

What you'd want in synchronous code is:

try{
try{
var res = $http.getSync("url");
res = someProcessingOf(res);
} catch (e) {
console.log("Got an error!",e);
throw e; // rethrow to not marked as handled
}
// do more stuff with res
} catch (e){
// handle errors in processing or in error.
}

承诺的版本非常相似:

$http.get("url").
then(someProcessingOf).
catch(function(e){
console.log("got an error in initial processing",e);
throw e; // rethrow to not marked as handled,
// in $q it's better to `return $q.reject(e)` here
}).then(function(res){
// do more stuff
}).catch(function(e){
// handle errors in processing or in error.
});

在 Angular $http 的情况下,Success ()和 error ()函数将有一个已经打开的响应对象,因此回调签名类似于 $http (...)。成功(函数(数据、状态、头、配置)

对于 then () ,您可能将处理原始响应对象。 such as posted in AngularJS $http API document

$http({
url: $scope.url,
method: $scope.method,
cache: $templateCache
})
.success(function(data, status) {
$scope.status = status;
$scope.data = data;
})
.error(function(data, status) {
$scope.data = data || 'Request failed';
$scope.status = status;
});

最后一个. catch (...)将不需要,除非在前一个承诺链中抛出了新的错误。

我认为前面的答案是正确的,但是这里有另一个例子(仅仅是 f.y.i,Success ()和 error ()根据 AngularJS 主页是不推荐的:

$http
.get('http://someendpoint/maybe/returns/JSON')
.then(function(response) {
return response.data;
}).catch(function(e) {
console.log('Error: ', e);
throw e;
}).finally(function() {
console.log('This finally block');
});

Forget about using success and error method.

这两种方法都不适用于角度1.4。基本上,贬值背后的原因是它们不是 可链式友好型,可以这么说。

通过下面的示例,我将试图演示关于 successerror不是 可链式友好型的含义。假设我们调用一个 API,它返回一个带有地址的用户对象:

用户对象:

{name: 'Igor', address: 'San Francisco'}

Call to the API:

$http.get('/user')
.success(function (user) {
return user.address;   <---
})                            |  // you might expect that 'obj' is equal to the
.then(function (obj) {   ------  // address of the user, but it is NOT


console.log(obj); // -> {name: 'Igor', address: 'San Francisco'}
});
};

发生什么事了?

因为 successerror返回 原始承诺,也就是 $http.get返回的 原始承诺,所以传递给 then回调的对象是整个 使用者对象,也就是说,传递给前一个 success回调的输入是相同的。

如果我们连接两个 then,就不会那么令人困惑了:

$http.get('/user')
.then(function (user) {
return user.address;
})
.then(function (obj) {
console.log(obj); // -> 'San Francisco'
});
};

I do it like Bradley Braithwaite suggests in his 博客:

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;
});
}])

重点:

  • 解析函数链接到。然后在我们的控制器中运行,例如一切正常,所以我们可以信守承诺并解决它。

  • 拒绝函数链接到。我们的控制器中的 catch 函数也就是说出了问题,所以我们不能遵守我们的承诺 拒绝它

它是相当稳定和安全的,如果你有其他条件拒绝的承诺,你总是可以过滤你的数据在成功的功能和调用 deferred.reject(anotherReason)与拒绝的原因。

正如 Ryan Vice 在评论 中所建议的那样,可以这样说,除非你稍微改变一下响应,否则这可能不会被视为有用。

因为 successerror从1.4开始就已经被弃用了,所以最好使用常规的承诺方法 thencatch,在这些方法中转换响应,并返回转换后的响应的承诺。

我用两种方法和第三种中间方法展示了同样的例子:

successerror方法(successerror返回 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;
};

thencatch方法(这种方法有点难测试,因为抛球的原因) :

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;
}

欢迎任何评论或修正。