产生一个取决于递归承诺的承诺

时间:2014-05-14 09:08:10

标签: javascript angularjs asynchronous promise q

我有一个整数id数组,例如

var a=[1,2,3,4,5]

我需要为每个id执行异步远程调用。每个调用都是使用$ resource执行的WebAPI请求,并显示为promise。

我需要创建一个获取这些ID数组的函数,然后初始化递归promises链。该链应该逐个导致对每个ID进行相应的webapi调用。这些调用不应该是平行的,而应该是链接的。

有问题的函数会返回一个“主”承诺,应根据异步Web调用的结果解决或拒绝该承诺。也就是说,如果由于与服务器断开连接而导致递归中的某些承诺被拒绝,那么主承诺也应该失败。在正常情况下,“主要”承诺必须在所有请求完成时解决。

如何在angularjs中实现这一目标?

2 个答案:

答案 0 :(得分:5)

您在数组上使用reduce将承诺链接在一起。没有必要让这个递归。

// for angularjs: var Q = $q.when;
var p = a.reduce(function(prev, el) {
    return prev.then(function(arr) {
        return makeRequest(el).then(function(res) {
             return arr.concat([res]);
         });
    });
}, Q([]));

答案 1 :(得分:2)

这实际上是一个非常合理的要求。

我们在没有特定.each控件的库中使用的工具是.then

var a = [1,2,3,4,5];
var p = makeRequest(a.shift()); // use first element
a.forEach(function(el){
    p = p.then(function(result){
        return makeRequest(el);
    });
});

p.then(function(){
    // all requests done
});

请注意,我假设您在此处使用makeRequest方法生成单个请求,并返回在请求完成时履行的承诺。

如果您需要使用辅助数组,也可以返回请求的结果:

var a = [1,2,3,4,5];
var results = Array(a.length);
var p = makeRequest(a.shift()).
        then(function(res){ results[0] = res;}); // use first element
a.forEach(function(el,i){
    p = p.then(function(result){
        results[i] = result;
        return makeRequest(el);
    });
});
p = p.thenResolve(results); // resolve with results, in BB that'd be p.return(results)

p.then(function(results){
    // all requests done
    console.log(results); // array of response values
}).catch(function(e){
    // single failure
});

使用Bluebird库的v2分支,您可以执行以下操作:

 Promise.each([1,2,3,4,5],makeRequest).then(function(results){
      // access results
 });