web-dev-qa-db-ja.com

一部の呼び出しが機能し、他の呼び出しが失敗すると、$ q.all()で何が起こりますか?

一部の呼び出しが機能し、他の呼び出しが失敗すると、$ 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配列にデータが入力されます。

1つが失敗すると、2番目の関数が呼び出され、エラー変数に詳細が与えられることは私の理解です。

ただし、一部の応答が機能し、他の応答が失敗した場合に何が起こるかを誰かが説明してくれますか?

62
Alan2

PromiseライブラリはQ実装に基づいているため、最初のpromiseが拒否されるとすぐに、拒否コールバックがエラーで呼び出されます。他の約束が解決されるのを待ちません。 Qhttps://github.com/kriskowal/q のドキュメントを参照してください。 Q.allの場合、これが言及されているものです

All関数は、値の配列のpromiseを返します。この約束が履行されると、配列には元の約束の履行値がそれらの約束と同じ順序で含まれます。指定された約束のいずれかが拒否された場合、返された約束はすぐに拒否され、残りのバッチを待機しません。

39
Chandermani

この質問が投稿されてからしばらく経ちましたが、おそらく私の答えが誰かを助けるかもしれません。私は、すべての約束を解決することで同様の問題を解決しましたが、返品があれば後で処理してエラーがないかどうかを確認できました。以下は、いくつかの画像アセットをプリロードするために使用した私の例です。

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
            }
        }
    }
);
38
Vexter

編集: 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;
        }
    });
});
6
Maruf

ここに小さな答えがあります。このフィドルでは、何らかの約束でエラーが発生した場合の動作を確認できます。

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

http://jsfiddle.net/wd9w0ja4/

5
user3232739

角度で$ qにallSettled機能を追加する新しいangularパッケージを見つけました:

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

4
birdy1980

$ httpの約束のエラー状態を$ qに渡す前に単純に処理できませんか?約束は連鎖しているので、これはうまくいくはずです:

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

明らかに、noopを任意の変換に変更できますが、これにより$q.all失敗から。

1
toxaq

私の場合、成功したか失敗したかに関係なく、最後の約束がいつ解決されたかを知る必要がありました。失敗するとすぐにダウンするため、$ q.allはオプションではありませんでした。すべてのデータが処理される(または処理されない)場合にのみユーザーをリダイレクトして、次のページにロードできるようにするためにこれが必要でした。だから私はこれで終わった:

  1. 実装された各promise/callも失敗コールバックで、成功コールバックと失敗コールバックの両方で「リダイレクト」関数が呼び出されます。
  2. この関数では、カウンターが設定され、呼び出しごとに増加します。これがプロミス/コールの数に達すると、次のビューにリダイレクトされます。

私はそれがそれを行うには非常に不十分な方法であることを知っていますが、それは私のために働いた。

0
Diomos