我以两种不同的方式向服务器询问一条信息。没有承诺,它可以如下工作
function callback(someData) {
displaySomeData();
}
request1(user.name, callback);
request2(user.id, callback);
两个请求都可能返回所需的信息 1 ,其中一个或两个可能没有结果。 callback
正确处理缺失的信息。
实际上,这两个请求可以简单地汇总到一个像
这样的单一请求中aggregateRequest(user, callback) {
request1(user.name, callback);
request2(user.id, callback);
}
我很好奇这是如何用承诺书写的。
我知道有一个$q.all(promises)
会在完成所有承诺时调用其then
参数。我想我需要像$q.each
这样的东西,每当一个承诺得到满足时就会调用它的参数。
在这个案例中使用promises是一个愚蠢的想法......但是混合使用承诺和回调会觉得很糟糕。
1 我们可以争辩说,如果第一个成功,它会按顺序保存请求。我们也可以争辩说,将两个请求结合起来会更有效率。但是现在让我们忘记它。
理想情况下,我想对两个请求做出反应,因为每个请求都可能返回值得合并的不同部分数据。我真的必须两次调用then
部分而且我害怕,这不是承诺的设计目的。
我可能会去all
。或者也许是Benjamin Gruenbaum any
的修改版本,只有在它足够好的情况下才会返回第一个结果(否则等待第二个结果并合并它们)。
答案 0 :(得分:2)
根据docs所有你需要处理的是all()
,这听起来不像你想要的那样。据我所知,你会被困在
request1(user.name).then(displaySomeData);
request2(user.id).then(displaySomeData);
我个人更喜欢回调方法。
答案 1 :(得分:1)
在$q
中没有内置方式来编写.any
方法,该方法可以使用多个方法中的一个方法解析。但是,写一个很简单。
function any(){
var rejected = 0;
var d = $q.defer();
for(var i = 0; i < arguments.length; i++){
arguments[i].then(function(val){ d.resolve(val); }).catch(function(el){
rejected++;
if(rejected == arguments.length) d.reject(new Error("All promises rejected"));
});
}
return d.promise();
}
any(promise1,promise2).then(function(value){
// access the value of the resolved promise (first one) here.
}).catch(function(err){
// error caught here if the above .then threw, or if all promises rejected
});
这是有效的,因为promise是一次性操作的抽象,只能解析一次。
不还原为回调。回调不是安全的,并且有错误处理问题,当你在多个图层中混合回调和承诺时,你就输了。
Promise是对多个事件触发概念的抽象,你需要它 - 一个事件发射器模式。承诺一旦解决就不会改变状态。
function each(promises, progressHandler){
return $q.all(promises.map(function(promise){
return promise.then(function(val){ progressHandler(val); return val; });
}));
}
这类似于$q.all
,除了它通过简单的事件发射器(如接口)通知您进度不属于承诺的一部分。用法是
each([p1,p2,p3],function(val){
// change progress bar width or notify data
}).then(function(values){
// here, all promises resolved
});
请注意,您也可以使用$q
内置notify
进度系统,但我相信,以及我在承诺社区中与之交谈的大多数人的信念,承诺通知是破碎了,将来可能会更换,所以我不会依赖它。