доступ к ng-ресурсу в функции через $ scope вызывает бесконечный цикл

0

У меня есть приложение Rails и доступ к двум моделям через JSON API с использованием ng-ресурса.

В моем шаблоне я показываю список первых "заказов" модели:

<li ng-repeat="order in orders">
  Order {{order.id}}: 
  Product: {{showProduct(order.product_id)}}
</li>

Каждый "заказ" содержит product_id. Теперь я хотел бы получить доступ ко второй модели ("продукты") и отобразить внутри ng-repeat правильный "продукт" с идентификатором product_id соответствующего "заказа".

Для этого я подумал об использовании функции showProduct() и использовал order.product_id в качестве аргумента. Однако, когда я делаю это, он вызывает бесконечный цикл, который продолжает делать запросы GET в мою базу данных.

Здесь важная часть моего приложения.

var app = angular.module('shop', ['ngResource']);

app.factory('models', ['$resource', function($resource){
  var orders_model = $resource("/orders/:id.json", {id: "@id"}, {update: {method: "PUT"}});
  var products_model = $resource("/products/:id.json", {id: "@id"}, {update: {method: "PUT"}});

  var o = { 
    orders: orders_model,
    products: products_model
  };
  return o;
}]);

app.controller('OrdersCtrl', ['$scope', 'models', function($scope, models){
  $scope.orders = models.orders.query();

  $scope.showProduct = function(product_id){
    return models.products.get({id: product_id});
  };
}])

Это ошибки в моей консоли (что имеет смысл, так как это бесконечный цикл):

Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: []

Uncaught Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: []

Запрос GET в консоли Rails кажется прекрасным. Возможно, я пытаюсь думать гораздо сложнее, чем мне нужно.

Теги:
ngresource

2 ответа

1
Лучший ответ

Да, потому что у вас есть showProduct в представлении, функция вызывается в каждом дайджесте, каждый раз возвращаясь к другому обещанию, чтобы он ломался:

  • вы создаете серверные запросы несколько раз за дайджест
  • каждый запрос отличается от другого
  • 10 итераций выполняются до тех пор, пока два значения не будут равны или это исключает исключение

Я предлагаю вам сделать:

models.orders.query().$promise
  .then(function(orders){
    $scope.orders = orders;
    //using lodash here, I recommend you use it too
    _.each(orders, function(order){
      models.products.get({id: order.product_id }).$promise
        .then(function(product){
          order.product = product;
        })
    });
  });

И в перспективе:

<li ng-repeat="order in orders">
  Order {{order.id}}: 
  Product: {{order.product}}
</li>

Но использование этого кода вызовет один запрос для каждого порядка, который является довольно плохим: его анти-шаблон N + 1.

2 решения:

  • иметь в заказе данные продукта напрямую
  • иметь один запрос со всеми идентификаторами продуктов
  • 0
    Большое спасибо! Это работает. Как бы я включил данные продукта непосредственно в заказ?
  • 0
    зависит , как вы создаете JSON :) остерегайтесь использовать includes в вашем ActiveRecord запроса , чтобы избежать на стороне сервера N + 1
Показать ещё 7 комментариев
0

Глядя на ваш код, я сначала почувствовал, что он должен работать. Во всяком случае, если это не так, я бы попробовал это так:

В вашем контроллере:

  $scope.showProduct = function(product_id){
    var product = models.products.get({id: product_id}, function(){
      return product;
    });
  };

Это вернет значение после поступления данных с сервера.

  • 0
    Он будет выполняться при каждом дайджесте, поэтому он тоже будет зависать

Ещё вопросы

Сообщество Overcoder
Наверх
Меню