生成一个依赖于递归承诺的承诺

Produce a promise which depends on recursive promises

本文关键字:承诺 依赖于 递归 一个      更新时间:2023-09-26

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

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

和我需要对每个id执行异步远程调用。每个调用都是一个WebAPI请求,使用$resource执行,并作为promise呈现。

我需要创建一个函数,它接受这些id的数组,然后初始化递归承诺链。这个链应该导致相应的webapi调用每个id,一个接一个。这些调用不应该是并行的,而应该是链式的。

所讨论的函数返回自己一个"main"承诺,应该根据异步web调用的结果来解决或拒绝。也就是说,如果递归中的某些承诺由于与服务器断开连接而被拒绝,则主承诺也应该失败。在正常情况下,"main" promise必须在所有请求完成时解决。

如何在angularjs中实现?

在数组上使用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([]));

这其实是一个非常合理的请求。

在没有特定.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
 });