2017-08-16 561 views
1

我真的和我的一点代码混淆,这是一个angularjs服务。我尝试使用Promise.all来连接作为服务一部分的两个promise,并将结果发送给我的控制器。 事情是由Promise.all返回的对象由两个相同的数组组成。 这里我的代码,只是为了更清楚:Promise.all()返回意想不到的值

batchModule.service('BatchService', ['$http', '$q', '$log', 'MessageboxService', function ($http, $q, $log, MessageboxService) { 

let deferred = $q.defer(); 

this.loadAll =() => { 

    promise1 =() => { 
     $http.get(_restApiPath + "/batch/?processtype=IMPORT_CUSTOMER") 
     // loadLastFiveBatch('IMPORT_CUSTOMER') 
      .then(function (response) { 
       deferred.resolve(response.data); 
       // datas.push(response1); 
       // console.log(datas); 
      }, function (error) { 
       deferred.reject(error); 
       $log.error(error); 
      }); 
     return deferred.promise; 
    }; 

    promise2 =() => { 
     $http.get(_restApiPath + "/batch/?processtype=IMPORT_LAB_MARGIN") 
     // loadLastFiveBatch('IMPORT_LAB_MARGIN') 
      .then(function (response) { 
       deferred.resolve(response.data); 
       // datas.push(response2); 
       // console.log(datas); 
      }, function (error) { 
       deferred.reject(error); 
       $log.error(error); 
      }); 
     return deferred.promise; 
    }; 

    Promise.all([promise1(), promise2()]) 
    .then(values => { 
     console.log(values); 
    }); 

}; 
}]); 

的的console.log(值)返回制成由IMPORT_CUSTOMER请求,返回2个等于阵列的一个目的,当Promise.all的第二个参数是一个恰恰promise由IMPORT_MARGIN请求返回。 我今天几个小时一直在研究它,但我找不到任何解决方案。 我希望我很清楚,我的英语不是很好。 谢谢您的回答:-)

+2

你只有一个单一的全球'deferred',所以它有点显而易见的,为什么它能够解析为只有一个值。当然,在第一个时候避免[deferred antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)地点! – Bergi

回答

1

问题造成的,因为你推迟了所有的承诺使用单一。因此,那个引用的单个内容会得到解决,它将解决您的承诺呼叫的更多实例。因此,对每个请求使用不同的延迟。我仍然不喜欢使用deferred anti-pattern。而是用$http.get方法建立承诺回报。

此外,您在函数的末尾有Promise.all,这将不会运行角度摘要循环。最终,如果您要更新来自此函数的任何绑定,则不会更新UI上的绑定。考虑chainging它使用$q.all

this.loadAll =() => { 

    promise1 =() => { 
     return $http.get(_restApiPath + "/batch/?processtype=IMPORT_CUSTOMER") 
      .then(function (response) { 
       return response.data; 
      }, function (error) { 
       $log.error(error); 
       return $q.reject(error); 
      } 
     ); 
    }; 

    promise2 =() => { 
     $http.get(_restApiPath + "/batch/?processtype=IMPORT_LAB_MARGIN") 
     // loadLastFiveBatch('IMPORT_LAB_MARGIN') 
      .then(function (response) { 
       return response.data; 
      }, function (error) { 
       $log.error(error); 
       return $q.reject(error); 
      } 
     ); 
    }; 
    //return is needed if any function is trying to chain `loadAll` function. 
    return $q.all([promise1(), promise2()]) 
    .then(values => { 
     console.log("promise1", values[0]); 
     console.log("promise2", values[1]); 
    }); 

}; 
1

您的承诺实际上都会返回相同的$q.defer();承诺。因此,您需要删除延迟的反模式(使用$q.defer()而不是return $http.get(..);),问题应该很好解决。

所以你的代码改成这样:

batchModule.service('BatchService', ['$http', '$q', '$log', 'MessageboxService', function ($http, $q, $log, MessageboxService) { 

    this.loadAll =() => { 

     promise1 =() => { 
      return $http.get(_restApiPath + "/batch/?processtype=IMPORT_CUSTOMER") 
       .then(response => response.data, error => { 
        $log.error(error); 
        return $q.reject(error); 
       }); 
     }; 

     promise2 =() => { 
      return $http.get(_restApiPath + "/batch/?processtype=IMPORT_MARGIN") 
       .then(response => response.data, error => { 
        $log.error(error); 
        return $q.reject(error); 
       }); 
     }; 

     $q.all([promise1, promise2]) 
     .then(values => { 
      console.log(values); 
     }); 
    }; 
}]); 
+0

非常感谢尼古拉。它确实工作得很好:-) –

+0

请注意'Promise.all'没有与AngularJS框架及其摘要循环集成。为了避免问题,可以使用**代替[$ q.all](https://docs.angularjs.org/api/ng/service/$q#all)。** AngularJS通过提供自己的事件来修改普通的JavaScript流处理循环。这将JavaScript分解为经典和AngularJS执行上下文。只有在AngularJS执行上下文中应用的操作才能受益于AngularJS数据绑定,异常处理,属性监视等。 – georgeawg

+0

将'Promise.all'更改为'$ q.all'。几乎只是盲目复制粘贴那部分。 :-) –