使用$ q.all在promise中调用promise

时间:2017-07-04 06:29:34

标签: javascript angularjs promise angular-promise

我有多个可以并行运行的api请求。

getlocations,getstates,get territories可以并行提出请求。但是,一旦我从getstates()调用获得状态列表,我需要为每个单独的状态发出api请求并解析状态对象。

这是我到目前为止的代码,可以通过这种方式在承诺中调用承诺吗?

  getAllLocations() {
    //make a promise call for all here .
    var promise = [];
    //first prmise
    promise.push(this.getAllLocations(Id).then(
        (locationsData) => {
            this.locations = locationsData;
        }));
    //second promise
    promise.push(this.getAllStates(Id).then(
        (resp) => {
            this.states = resp.data;
            //for each state , need to make an api call and add to the state info
            angular.forEach(this.states, function(state){
                var nodeId = state.Id;
                this.getStateSummary(nodeId).then((resp) => {
                    state.healthStatus = resp.data.operationalStatus;
                });
            },this)
        }));
    //third promise
    promise.push(this.getAllterritories(Id).then(
        (resp) => {
            this.territories = resp.data;
        }));
    //after all promises parse teh location data
    $q.all(promise).then(() => {
        for (var i = 0; i < this.locations.length; i++) {
            //do something with with location here
        }
        this.gridData = this.locations;
    });
}

如果没有,最好的方法是使用getStatesummary()调用吗?

2 个答案:

答案 0 :(得分:1)

我简化了3个承诺中的每一个(特别是1和3),因此this.locations,this.states和this.territories都在$ q.all中更新了。然后你就不知道了。 ; t必须,但我认为它使代码更具可读性

接下来,将所有3个承诺分配给变量(下面的代码中的p1,p2,p3)

下一个问题是等待所有状态API调用完成 - 另外需要$ q.all

总而言之,有了额外的ES6优点,你得到了

getAllLocations() {
    //first prmise
    const p1 = this.getAllLocations(Id);
    //second promise
    const p2 = this.getAllStates(Id).then(resp => 
        //for each state , need to make an api call and add to the state info
        $q.all(resp.map(state => this.getStateSummary(state.Id).then(resp => state.healthStatus = resp.data.operationalStatus)))
        .then(() => resp) // so we return data for this.states
    );
    //third promise
    const p3 = this.getAllterritories(Id).then(resp => resp.data);
    //after all promises parse teh location data
    $q.all([p1, p2, p3]).then(([locations, states, territories]) => {
        this.locations = locations;
        this.states = states;
        this.territories = territories;
        for (var i = 0; i < locations.length; i++) {
            //do something with with location here
        }
        this.gridData = this.locations;
    });
}

如果getAllStates promise返回一个Object而不是我假设它是一个数组 - 那么用

替换内部$q.all
        $q.all(Object.entries(resp).map(([key, state]) => this.getStateSummary(state.Id).then(resp => state.healthStatus = resp.data.operationalStatus)))

实际上,上面的代码同样适用于Array或Object:p

答案 1 :(得分:0)

您可以使用承诺链一个接一个地发送捕获承诺

 getAllLocations() {
     //make a promise call for all here .
     var promise = [];
     //first prmise
     this.getAllLocations(Id)
         .then(
             (locationsData) => {
                 this.locations = locationsData;
                 promise.push(this.locations);

                 return this.getAllStates(Id)
             }).then(
             (resp) => {
                 this.states = resp;
                 //for each state , need to make an api call and add to the state info
                 angular.forEach(this.states, function(state) {
                     var nodeId = state.Id;
                     return this.getStateSummary(nodeId);
                 }, this)
                 return this.getAllterritories(Id);
             }).then((resp) => {
             state.healthStatus = resp.data.operationalStatus;
             promise.push(state.healthStatus);
         }).then(
             (resp) => {
                 this.territories = resp.data;
                 promise.push(this.territories);
                 this.callAll(promise)
             })
 }


 callAll(promise) {
     //after all promises parse teh location data
     this.$q.all(promise).then(() => {
         for (var i = 0; i < this.locations.length; i++) {
             //do something with with location here
         }
         this.gridData = this.locations;
     });
 }