2013-03-08 17 views
98

ho una singola fabbrica definita con ngResource:AngularJS - attendere più query di risorse per completare

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

sto facendo più chiamate al metodo query definita in questa fabbrica. Le chiamate possono avvenire in modo asincrono, ma ho bisogno di aspettare che le chiamate per completare prima di continuare:

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

C'è un modo per fare questo con AngularJS fabbriche definiti con ngResource, simile a quella di jQuery $ .quando() poi.() funzionalità? Preferirei non aggiungere jQuery al mio progetto attuale.

risposta

188

Si desidera utilizzare le promesse e $q.all().

Fondamentalmente, è possibile utilizzarlo per avvolgere tutte le chiamate $ risorse o $ http perché restituiscono le promesse.

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... 
}); 
+16

Le risorse non restituiscono promesse, restituiscono gli oggetti da riempire in futuro. Tuttavia, nella versione * unstable * 1.1.3, le risorse hanno anche la proprietà '$ then' ma non espongono alcun oggetto promessa. Esporre '$ promise' completamente sarebbe in 1.1.4 –

+0

@ UmurKontacı Questo purtroppo non * * in 1.1.4 angolare! – nh2

+0

Dettagli su * risorse non sono promesse problema * può essere trovato in [questo thread] (https://groups.google.com/forum/#!msg/angular/N5yBJvl7Pbg/C48oelQu6DgJ) e in [questa richiesta pull] (https://github.com/angular/angular.js/pull/2060#issuecomment-17026079). – nh2

16

Credo che una soluzione migliore è:

$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

Per me ha lavorato senza $ promise alla fine ... Proprio come: Account.query ({type: 'billing'}), Account.query ({type: 'shipping'}) – georgeos

10

La soluzione da Ben Lesh è il migliore, ma non è completa. Se è necessario gestire le condizioni di errore - e, sì, è fare - allora è necessario utilizzare il metodo catch sulle API promessa in questo modo:

$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... 

}); 

Se non si definisce catch e tutti i tuoi promesse fallire, quindi il metodo then non verrà mai eseguito e quindi probabilmente lascerà la tua interfaccia in cattivo stato.

Problemi correlati