AngularJS - tunggu beberapa kueri sumber daya selesai

105

Saya memiliki satu pabrik yang ditentukan dengan ngResource:

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

Saya membuat beberapa panggilan ke metode kueri yang ditentukan di pabrik ini. Panggilan dapat terjadi secara asinkron, tetapi saya harus menunggu kedua panggilan selesai sebelum melanjutkan:

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

Apakah ada cara untuk melakukan ini dengan pabrik AngularJS yang ditentukan dengan ngResource, mirip dengan fungsionalitas $ .when (). Then () jQuery? Saya lebih suka untuk tidak menambahkan jQuery ke proyek saya saat ini.

Nathan Donze
sumber

Jawaban:

200

Anda akan ingin menggunakan promise dan $ q.all () .

Pada dasarnya, Anda dapat menggunakannya untuk menggabungkan semua panggilan $ resource atau $ http karena mereka mengembalikan 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...
});
Ben Lesh
sumber
17
Sumber daya tidak mengembalikan janji, mereka mengembalikan objek untuk diisi di masa depan. Namun dalam versi 1.1.3 yang tidak stabil , resource juga memiliki $thenproperti tetapi tidak menampilkan objek promise apa pun. Mengekspos $promisesepenuhnya akan berada di 1.1.4
Umur Kontacı
@ UmurKontacı Sayangnya ini tidak dalam sudut 1.1.4!
nh2
Rincian tentang sumber daya tidak menjanjikan masalah dapat ditemukan di utas ini dan dalam permintaan tarik ini .
nh2
1
Jawaban ini menunjukkan bagaimana menulisnya setelah diterapkan.
nh2
3
Jawaban Anda sangat membantu dan saya percaya ini adalah cara paling masuk akal untuk mengubah sumber daya menjadi janji dalam sudut pandang saat ini. Mungkin berguna untuk menambahkannya dalam dokumentasi $q, yang Anda tautkan, ini menjamin bahwa larik hasil berada dalam urutan yang sama dengan larik promise.
nh2
20

Saya pikir solusi yang lebih baik adalah:

$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...
});
Tales Mundim Andrade Porto
sumber
1
Bagi saya bekerja tanpa $ promise di akhir ... Sama seperti: Account.query ({type: 'billing'}), Account.query ({type: 'shipping'})
georgeos
12

Solusi dari Ben Lesh adalah yang terbaik tetapi belum lengkap. Jika Anda perlu menangani kondisi kesalahan - dan, ya, Anda melakukannya - maka Anda harus menggunakan catchmetode pada promise API seperti ini:

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

});

Jika Anda tidak mendefinisikan catch dan semua janji Anda gagal, maka thenmetode tersebut tidak akan pernah dijalankan dan dengan demikian mungkin akan membuat antarmuka Anda dalam keadaan buruk.

Nick A. Watts
sumber