使用$ q.catch同步多个Angular $ http调用和$ q /错误处理

时间:2016-05-25 22:26:59

标签: javascript angularjs asynchronous

我无法正确使用角度$q和Javascript' promise api。然后,我对Javascript很新,可能会出现语法错误。

This问题似乎相似,但它似乎并不是一个精确的副本...

我的服务有这样的方法(由我的控制器调用):

self.getResources = function() {

    let promises = [];

    for (let resourceName in $rootScope.resourceNameList) {

        promises.push($http({ 
            url : '/' + resourceName,
            method : 'GET' 
        }).then(function (res) { 
            return { resourceName : res.data};
        }));
    }
    return promises;
};

我的控制器将返回的承诺列表传递给有角度的$q.all()

let promises = resourceService.getResources();

$q.all(promises).then(function (resultsArray) {

    // resultsArray should be an array of elements like:
    // [ {cars : [...]}, {coffeePots : [...]}, {motorBoats : [...]} ]
    // with size = resourceNameList.length(), correct? 

    // this log is never called.
    console.log(resultsArray);
    $scope.resources = resultsArray;
});

最后,在我的HTML中,我尝试迭代并显示资源:

.
.
.
<!-- 'cars' is and example, but I am trying to retrieve this data in the same way -->
<tr ng-repeat="item in resources[cars]">
    <td>{{item.property1}}</td>
    <td>{{item.property2}}</td>
</tr>

该表未显示任何结果。

我可以从控制台看到HTTP请求成功并返回数据,因此我必须使用promise$q apis时出错。

有什么建议吗?

非常感谢。

2 个答案:

答案 0 :(得分:2)

我知道这可能是一个非答案,因为你已经发现你的输入数据集确实存在错误,但是你应该通过添加.catch来实际检测到这类问题(至少)你的根承诺,所以你可以立即看到实际上是什么。

在您的情况下,这是您的根承诺(已经附加了捕获)。 为了清晰起见,我把它分成了新行:

let promises = resourceService.getResources();

$q
 .all(promises)

 // unfortunately, .then only gets executed if all of these promises succeed.
 .then(function (resultsArray) {
   console.log(resultsArray);
   $scope.resources = resultsArray;
 })

 // there is a disturbance in the force!
 .catch(function (error) {
    // you can console.log(error) OR
    window.open("https://stackoverflow.com/search?q="+error.message);
 })
 ;

编辑:如果您需要在$q.all上过滤掉失败的承诺,只需将其替换为$q.allSettled!完整API在此处:https://github.com/kriskowal/q

要分享的其他一些想法:很快,您会发现自己抱怨$q缺少某些功能,例如将.push.map.all结合使用等等。已经有了一个图书馆;你可以使用BluebirdJS!角度为here's a nifty wrapper for it。相反,你的代码看起来像这样:

Promise.map($rootScope.resourceNameList, function(resourceName) {
      return $http({ 
        url : '/' + resourceName,
        method : 'GET' 
      });
}, {concurrency: 3}) // did I mention you could control concurrency?
.then(function(results) {
  console.log(results); // $http promises that were resolved!
},function(rejects) {
  console.log(rejects); // $http promises that were rejected :(
})
.catch(function (error) {
    // you can console.log(error) OR
    window.open("https://stackoverflow.com/search?q="+error.message);
})
;

好多了,对吧?

快乐的编码!以下是关于承诺的精彩内容:http://taoofcode.net/promise-anti-patterns/

答案 1 :(得分:0)

您需要在指令中注入$ q和$ http,如此

self.getResources = function($q,$http) {

let promises = [];

for (let resourceName in $rootScope.resourceNameList) {

    promises.push($http({ 
        url : '/' + resourceName,
        method : 'GET' 
    }).then(function (res) { 
        return { resourceName : res.data};
    }));
}
return promises;

};