AngularJS-複数のリソースクエリが完了するのを待つ


105

ngResourceで定義された単一のファクトリがあります。

App.factory('Account', function($resource) {
    return $resource('url', {}, {
        query: { method: 'GET' }
    });
});

このファクトリーで定義されたqueryメソッドを複数回呼び出しています。呼び出しは非同期で発生する可能性がありますが、続行する前に両方の呼び出しが完了するのを待つ必要があります。

App.controller('AccountsCtrl', function ($scope, Account) {
    $scope.loadAccounts = function () {
        var billingAccounts = Account.query({ type: 'billing' });
        var shippingAccounts = Account.query({ type: 'shipping' });

        // wait for both calls to complete before returning
    };
});

jQueryの$ .when()。then()機能と同様に、ngResourceで定義されたAngularJSファクトリでこれを行う方法はありますか?現在のプロジェクトにjQueryを追加したくない。

回答:


200

promise$ q.all()を使用する必要があります

基本的に、$ resourceまたは$ http呼び出しはすべてpromiseを返すため、これを使用してラップできます。

function doQuery(type) {
   var d = $q.defer();
   var result = Account.query({ type: type }, function() {
        d.resolve(result);
   });
   return d.promise;
}

$q.all([
   doQuery('billing'),
   doQuery('shipping')
]).then(function(data) {
   var billingAccounts = data[0];
   var shippingAccounts = data[1];

   //TODO: something...
});

17
リソースはプロミスを返さず、将来埋められるオブジェクトを返します。ただし、不安定版1.1.3バージョンでは、リソースにも$thenプロパティがありますが、promiseオブジェクトは公開されません。$promise完全に公開することは、1.1.4
UmurKontacı2013年

@UmurKontacı残念ながら、角度1.1.4ではありません
nh2 2013

リソースに関する詳細は約束ではありません。問題このスレッドこのプルリクエストにあります。
nh2 2013

1
この回答は、実装された後の記述方法を示しています。
nh2 2013

3
あなたの答えは非常に役に立ちます。それが現在の角度でリソースをプロミスに変換する最も賢明な方法だと思います。$qリンクしたのドキュメントに追加すると、結果の配列がpromise配列と同じ順序になることが保証されます。
nh2 2013年

20

より良い解決策は次のとおりです。

$q.all([
   Account.query({ type: 'billing' }).$promise,
   Account.query({ type: 'shipping' }).$promise
]).then(function(data) {
   var billingAccounts = data[0];
   var shippingAccounts = data[1];

   //TODO: something...
});

1
私は最後に$ promiseなしで作業しました...同様に:Account.query({type: 'billing'})、Account.query({type: 'shipping'})
georgeos

12

Ben Leshのソリューションは最適ですが、完全ではありません。エラー条件を処理する必要がある場合(そして、そうです)、次に、次のcatchようにpromise APIでメソッドを使用する必要があります。

$q.all([
   doQuery('billing'),
   doQuery('shipping')
]).then(function(data) {
   var billingAccounts = data[0];
   var shippingAccounts = data[1];

   //TODO: something...

}).catch(function(data) {

   //TODO: handle the error conditions...

}).finally(function () {

  //TODO: do final clean up work, etc...

});

定義せずにcatchすべてのpromiseが失敗した場合、thenメソッドは実行されないため、おそらくインターフェースが悪い状態のままになります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.