我一直在阅读关于$ q和承诺的几天,我似乎也明白了......我在实践中遇到以下情况:
如果第一次呼叫失败,则返回“无数据”,如果成功并说可以进行呼叫,则进行第二次呼叫,如果不是 - 再次“无数据”。如果第二次调用成功,则返回数据,如果不是 - “无数据”。它看起来像这样(大约,我简化了一般的想法,所以不要担心这里的小错误):
return $http.get (something)
.then(function(allowedAccess){
if(allowedAccess){
return $http.get (somethingElse)
.then( function(result){return {data:result} },
function(error){return {data:"n0pe"} }
)
} else {
return {data:"n0pe"}
}
},
function(){ return {data:"n0pe"} });
我被告知在这里使用$ q。我真的不明白我会怎样或为什么。 $ http电话已经是承诺。
如果有办法让这个更清洁,我看不到它。刚刚完成重新阅读post on the subject。基本上,我错过了什么/有更好的方法吗?
编辑:也只是重新阅读a tutorial on chaining promises - 它根本不处理呼叫失败。基本上将此作为尽职调查发布。
编辑2:这是关于我所询问的理论的详细说明,摘自第一篇文章:
这是一个简单的例子。如果你的then()回调返回另一个promise,它会变得非常强大。在这种情况下,下一个then()只会在承诺结算后执行。例如,此模式可用于串行HTTP请求(请求取决于前一个请求的结果):
这似乎是在谈论像这样的链:
asyncFn1(1)
.then(function(data){return asyncFn2(data)})
.then(function(data){return asyncFn3(data)})
所以,如果我理解正确的话a)。不适用于我,因为我没有第三功能。 B)。如果我有三个函数会适用于我,因为当我在第一个$ http请求中运行if语句时,只有在if语句中我才会返回另一个promise。所以,理论上,如果我有三个异步函数来链接,我需要将我的if语句放在一个promise中吗?
答案 0 :(得分:13)
Promise确实有助于进行异步调用的代码组合。换句话说,它们允许您以与编写同步调用集的方式类似的方式编写代码(使用链式.then
),并且好像同步代码位于{{ 1}} / try
阻止(带catch
)。
所以,想象一下你的HTTP调用是阻塞的 - 你的逻辑就是这样:
.catch
你可以稍微简化一下:
var allowedAccess, data;
try {
allowedAccess = $http.get(something);
if (allowedAccess){
try{
var result = $http.get(somethingElse);
data = {data: result};
} catch (){
data = {data: "n0pe"};
}
} else {
data = {data: "n0pe"};
}
} catch (){
data = {data: "n0pe"};
}
return data;
这将转换为异步版本:
var allowedAccess, result;
try {
allowedAccess = $http.get(something);
var result;
if (allowedAccess) {
result = $http.get(somethingElse);
} else {
throw;
}
data = {data: result};
} catch () {
data = {data: "n0pe"};
}
return data;
至少,这是在使用分支和异步调用编写代码时可以应用的原因。
我并不是说我提供的版本是最佳的或更短的 - 是 ,但是,由于单个错误处理,更多的DRY。但只是意识到当你执行return $http
.get(something)
.then(function(allowedAccess){
if (allowedAccess){
return $http.get(somethingElse);
} else {
return $q.reject(); // this is the "throw;" from above
}
})
.then(function(result){
return {data: result};
})
.catch(function(){
return {data: "n0pe"};
})
时,它相当于.then(success, error)
/ try
,而不是之前的异步操作 - 根据您的具体情况,这可能需要也可能不需要。
答案 1 :(得分:-2)
$ q将有助于减少这样的调用金字塔:
async-call1.then(...
aysnc-call2.then(...
此博客文章 - http://chariotsolutions.com/blog/post/angularjs-corner-using-promises-q-handle-asynchronous-calls/ - 提供了一种制作多个HTTP请求的简洁方法。注意使用$ q的清洁方法。如果您遇到单个HTTP端点,使用您的方法就可以了。我说,你所拥有的也很好; $ q可能会在未来提供更大的灵活性。
博客文章描述了使用$ q时的服务,代码看起来更干净。
service('asyncService', function($http, $q) {
return {
loadDataFromUrls: function(urls) {
var deferred = $q.defer();
var urlCalls = [];
angular.forEach(urls, function(url) {
urlCalls.push($http.get(url.url));
});
// they may, in fact, all be done, but this
// executes the callbacks in then, once they are
// completely finished.
$q.all(urlCalls)
.then(...
我也是承诺的初学者,所以带着一点点盐。