AngularJS - đợi nhiều truy vấn tài nguyên hoàn thành


105

Tôi có một nhà máy duy nhất được xác định bằng ngResource:

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

Tôi đang thực hiện nhiều cuộc gọi đến phương thức truy vấn được xác định trên nhà máy này. Các cuộc gọi có thể xảy ra không đồng bộ, nhưng tôi cần đợi cả hai cuộc gọi hoàn tất trước khi tiếp tục:

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ó cách nào để thực hiện việc này với các nhà máy AngularJS được định nghĩa bằng ngResource, tương tự như chức năng $ .when (). Then () của jQuery không? Tôi không muốn thêm jQuery vào dự án hiện tại của mình.

Câu trả lời:


200

Bạn sẽ muốn sử dụng các lời hứa và $ q.all () .

Về cơ bản, bạn có thể sử dụng nó để gói tất cả các lệnh gọi $ resource hoặc $ http của mình vì chúng trả về các lời hứa.

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
Tài nguyên không trả lại lời hứa, chúng trả về các đối tượng sẽ được lấp đầy trong tương lai. Tuy nhiên trong phiên bản 1.1.3 không ổn định , tài nguyên cũng có thuộc $thentính nhưng không để lộ bất kỳ đối tượng hứa hẹn nào. Phơi bày $promisehoàn toàn sẽ có trong 1.1.4
Umur Kontacı Ngày

@ UmurKontacı Rất tiếc, điều này không có trong 1.1.4 góc!
nh2

Thông tin chi tiết về vấn đề tài nguyên không phải là lời hứa có thể được tìm thấy trong luồng này và trong yêu cầu kéo này .
nh2

1
Câu trả lời này cho thấy cách viết nó khi nó được triển khai.
nh2 30/04/2013

3
Câu trả lời của bạn rất hữu ích và tôi tin rằng đó là cách hợp lý nhất để chuyển đổi tài nguyên thành lời hứa trong góc độ hiện tại. Có thể hữu ích nếu bạn thêm điều đó vào tài liệu $qmà bạn đã liên kết đến, nó đảm bảo rằng mảng kết quả có cùng thứ tự với mảng hứa hẹn.
nh2

20

Tôi nghĩ một giải pháp tốt hơn là:

$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
Đối với tôi, tôi đã làm việc mà không có lời hứa nào vào cuối ... Cũng giống như: Account.query ({type: 'billing'}), Account.query ({type: 'shipping'})
georgeos

12

Giải pháp từ Ben Lesh là tốt nhất nhưng nó không hoàn chỉnh. Nếu bạn cần xử lý các điều kiện lỗi - và, có, bạn có - thì bạn phải sử dụng catchphương thức trên API hứa như thế này:

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

});

Nếu bạn không xác định catchvà tất cả các lời hứa của bạn không thành công, thì thenphương thức sẽ không bao giờ thực thi và do đó có thể khiến giao diện của bạn ở trạng thái xấu.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.