AngularJS - дочекайтеся завершення кількох запитів на ресурси


105

У мене є одна фабрика, визначена з ngResource:

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

Я роблю кілька дзвінків до способу запиту, визначеного на цій фабриці. Дзвінки можуть відбуватися асинхронно, але мені потрібно дочекатися завершення обох дзвінків, перш ніж продовжувати:

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

Чи є спосіб це зробити з фабриками AngularJS, визначеними за допомогою ngResource, аналогічно функціоналу $ .when ()., Тоді () jQuery? Я вважаю за краще не додавати jQuery до свого поточного проекту.

Відповіді:


200

Ви хочете використовувати обіцянки та $ q.all () .

В основному, ви можете використовувати його, щоб обернути всі ваші $ ресурси або $ http дзвінки, оскільки вони повертають обіцянки.

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повністю було б в 1.1.4
Umur Kontacı

@ UmurKontacı Це, на жаль, не в куті 1.1.4!
nh2

Деталі про ресурси не є обіцянками Проблему можна знайти в цій темі та в цьому запиті на витяг .
nh2

1
Ця відповідь показує, як записати його, як тільки це буде реалізовано.
nh2

3
Ваша відповідь дуже корисна, і я вважаю, що це найрозумніший спосіб перетворити ресурси на обіцянки в поточному кутовому. Може бути корисним додати, що в документації, з $qякою ви пов’язані, він гарантує, що масив результатів знаходиться в тому ж порядку, що і масив обіцянок.
nh2

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
Для мене працював без $ обіцянок наприкінці ... Так само, як: Account.query ({type: 'billing'}), Account.query ({type: 'shipping'})
georgeos

12

Рішення від Бена Леша найкраще, але воно не є повним. Якщо вам потрібно обробити умови помилок - і, так, ви це зробите - тоді ви повинні використовувати catchметод на 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і всі ваші обіцянки не вдасться, тоді thenметод ніколи не виконається, і, таким чином, ви зможете залишити ваш інтерфейс у поганому стані.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.