当一些调用工作而其他调用失败时,$ q.all()会发生什么?

时间:2013-11-13 03:51:36

标签: javascript angularjs angular-promise

当某些调用工作而其他调用失败时,$ q.all()会发生什么?

我有以下代码:

    var entityIdColumn = $scope.entityType.toLowerCase() + 'Id';
    var requests = $scope.grid.data
      .filter(function (rowData, i) {
          return !angular.equals(rowData, $scope.grid.backup[i]);
      })
      .map(function (rowData, i) {
          var entityId = rowData[entityIdColumn];
          return $http.put('/api/' + $scope.entityType + '/' + entityId, rowData);
      });
    $q.all(requests).then(function (allResponses) {
        //if all the requests succeeded, this will be called, and $q.all will get an
        //array of all their responses.
        console.log(allResponses[0].data);
    }, function (error) {
        //This will be called if $q.all finds any of the requests erroring.
        var abc = error;
        var def = 99;
    });

当所有$ http调用都工作时,allResponses数组将填充数据。

当一个人失败时,我的理解是将调用第二个函数并给出错误变量详细信息。

但有人可以帮我解释一下,如果某些回复有效并且其他回复失败会发生什么?

7 个答案:

答案 0 :(得分:39)

我相信,因为promise库基于Q实现,所以一旦第一个promise被拒绝,就会调用拒绝回调并显示错误。它不等待其他承诺得到解决。请参阅Q https://github.com/kriskowal/q的文档。对于Q.all,这就是提到的

  

all函数返回值数组的promise。当这个   承诺得到满足,数组包含了履行的值   原始承诺,与承诺的顺序相同。如果其中之一   如果承诺被拒绝,则返回的承诺立即生效   拒绝,而不是等待批次的其余部分。

答案 1 :(得分:38)

自问题发布以来已经有一段时间了,但也许我的回答可能仍然对某人有所帮助。我通过简单地解决所有承诺解决了类似的问题,但是我可以稍后处理返回并查看是否有任何错误。以下是我用于预加载某些图片资源的示例:

var loadImg = function(imageSrc) {
    var deferred = $q.defer();

    var img = new Image();
    img.onload = function() {
        deferred.resolve({
            success: true,
            imgUrl: imageSrc
        });
    };
    img.onerror = img.onabort = function() {
        deferred.resolve({
            success: false,
            imgUrl: imageSrc
        });
    };
    img.src = imageSrc;

    return deferred.promise;
}

稍后我可以看到哪些是错误的:

var promiseList = [];
for (var i = 0; i < myImageList.length; i++) {
    promiseList[i] = loadImg(myImageList[i]);
}
$q.all(promiseList).then(
    function(results) {
        for (var i = 0; i < results.length; i++) {
            if (!results[i].success) {
                // these are errors
            }
        }
    }
);

答案 2 :(得分:6)

编辑:仅在Kris Kowal的Q中受到支持 - 但仍然是有用的花絮

如果您想要处理所有这些内容而不立即拒绝,请使用allSettled

这是文档所说的内容:

  

如果你想等待所有的承诺要么得到满足,要么   拒绝,你可以使用allSettled。

Q.allSettled(promises)
.then(function (results) {
    results.forEach(function (result) {
        if (result.state === "fulfilled") {
            var value = result.value;
        } else {
            var reason = result.reason;
        }
    });
});

答案 3 :(得分:5)

这是一个小答案。 如果在某些承诺中出现错误,你可以看到它是如何工作的。

$q.all([test1(), test2()]).then(function() {
  // success
}, function() {
  // error
});

http://jsfiddle.net/wd9w0ja4/

答案 4 :(得分:4)

我找到了一个新的角度包,它将allSettled功能添加到$ q in angular:

https://github.com/ohjames/angular-promise-extras

答案 5 :(得分:1)

你能不能简单地处理$ http承诺的错误条件,然后再将它们传递给$ q?承诺被束缚,所以这应该有效:

return $http.put('/api/' + $scope.entityType + '/' + entityId, rowData).then(function(r){return r;}, angular.noop);

显然,您可以将noop更改为您想要的任何转换,但这会阻止阻止$q.all失败的拒绝。

答案 6 :(得分:0)

在我的情况下,无论成功还是失败,我都需要知道最后的承诺何时得到解决。 $ q.all不是一个选项,因为如果一个失败,它会立即下降。我需要这个以确保用户将被重定向,无论如何,但只有处理(或不处理)所有数据,以便可以在下一页加载它们。所以我最终得到了这个:

  1. 实施的每个promise / call也会失败回调,其中成功和失败回调都会调用“redirect”函数。
  2. 在此功能计数器中设置,每次调用都会增加。如果这达到了承诺/呼叫的数量,则重定向到下一个视图。
  3. 我知道这样做很蹩脚,但它对我有用。