Пользовательская директива, вызывающая функцию $scope, вызывает $rootScope:infdig

Я попытался изучить другие вопросы $rootScope:infdig здесь и не смог найти ни одного, который действительно объяснил бы мне это хорошо или который я понял. То же самое с документами AngularJs. Я надеюсь, что кто-то может помочь.

У меня есть функция, которую я сделал для $scope, которая принимает один параметр и вызывает запрос API GET и возвращает объект json только с «id» и «name». Затем эта функция возвращает имя из объекта обратно в директиву, которая его вызывает.

Функция вызывается из директивы, но как только это происходит, она застревает с ошибкой сотни таких «rootScope:infdig» в секунду. Директива также никогда не отображает текст возвращаемого «имени». Я знаю, что http-вызов работает, потому что после этого я регистрирую «имя» в консоли.

Экран ошибки

Вот мой контроллер:

owlyfm.controller('landingPageController', [ "$scope", "$log", "$http", "$location", "apiUrlsService", function ($scope, $log, $http, $location, apiUrlsService) {

 $http.get("https://api.backand.com:443/1/objects/Albums?pageSize=3&pageNumber=1&deep=true&relatedObjects=true")
    .success( function(result){
        $scope.featuredAlbums = result.data;
        //$log.info($scope.featuredAlbums);
    })
    .error( function(data, status){
        $log.error(data);
    });

    $scope.getAlbumArtist = function(artistId){

      $http.get("https://api.backand.com:443/1/objects/Artists/" + artistId)
        .success(function(result){
          var artistsName = result.name;
          $log.info(artistsName);
          return artistsName;
        });
    }
}]);

Вот где я создал директиву:

owlyfm.directive("featuredAlbum", function(){

return{
    restrict: 'E',
    templateUrl: 'directives/featuredAlbum.html',
    scope: {
        albumObject: "=",
        getAlbumArtistFunction: "&"
    }
  }
});

Здесь я вызываю директиву в представлении

<div class="row fluid-container" >
    <featured-album ng-repeat="featuredAlbum in featuredAlbums" album-object="featuredAlbum" get-album-artist-function="getAlbumArtist(album)" class="col-md-4" ></featured-album>
</div>

А вот и сама директива:

    <div class="featuedAlbum">

        <div>
            <img class="img-responsive" ng-src=" {{albumObject.albumArtUrl}} "/>
        </div>

        <h4>{{ albumObject.name }}</h4>
        <h5>{{ getAlbumArtistFunction( { album: albumObject.Artists } ) }}</h5>
        <h6>{{ albumObject.releaseDate }}</h6>

    </div>

Что я делаю

Подводя итог, я вызываю API для получения объекта альбома (кстати, я использую Backand). Как только я получаю этот объект альбома, я визуализирую теги <img> и <h> с данными, которые я получаю. Это работает нормально.

Объект альбома имеет идентификатор, имя, дату, imgUrl и «Исполнители» (это просто идентификатор исполнителя). Затем я использую этот идентификатор «artists», чтобы сделать еще один вызов, чтобы получить фактический объект Artist, связанный с ним. Вот где возникает проблема.

Эта проблема

Это вызов http для объекта artist, который вызывает цикл ошибок. Несмотря на то, что я вижу в журнале, что он получает json-объект художников, он не отправляет его в директиву.

Что я исследовал

Я читал, что есть проблемы с использованием ng-repeat с функциями из директивы. Однако я не совсем понимаю, почему и как это применимо здесь, и я не знаю, как бы я изменил его, чтобы сделать то, чего я пытаюсь достичь. Все остальные вопросы здесь немного выше моей головы.

Если бы кто-нибудь мог мне помочь, это было бы очень признательно.


person Joshua Shoemaker    schedule 11.01.2016    source источник
comment
забудьте об angular 1, скоро будет angular 2 и в бета-версии!   -  person Kevin Simple    schedule 11.01.2016
comment
Я бы посоветовал не делать никаких http-запросов в функции, вызываемой в поле зрения: она будет вызываться сотни раз. И я думаю, что проблема бесконечного дайджеста должна исчезнуть после этого.   -  person Haocheng    schedule 11.01.2016
comment
Это похоже на состояние гонки. $http является асинхронным и возвращает обещание. Вы перебираете массив и для каждой строки в своем массиве выполняете вызов $http; каждый возвращенный вызов будет инициировать цикл $digest, который затем будет повторно проходить через массив и повторно инициировать вызовы $http, фактически бесконечно зацикливая ваш код.   -  person Claies    schedule 11.01.2016
comment
вы можете решить эту проблему, используя предложение track by для ng-repeat, используя синтаксис одноразовой привязки :: для ::getAlbumArtistFunction, или и то, и другое. Однако такое количество $http вызовов подряд, как это, является узким местом в производительности, и вам лучше спроектировать конкретную конечную точку на сервере, которая может возвращать объединенную информацию за один вызов.   -  person Claies    schedule 11.01.2016
comment
Спасибо за помощь, ребята! @Haocheng Спасибо за ваш вклад, как бы вы посоветовали мне сделать этот вызов для отображения данных в представлении?   -  person Joshua Shoemaker    schedule 11.01.2016
comment
И @Claies, это то, что я бы предпочел, но я все еще привыкаю к ​​службе API Backands. Когда я когда-либо вызываю объект, я получаю возможность вызывать объекты, связанные с ним, но мне трудно копаться в json, чтобы получить их. Объекты, которые я вызываю, всегда находятся в данных объекта, а связанные объекты всегда находятся в другом объекте, называемом relatedObjects, который не находится внутри данных.   -  person Joshua Shoemaker    schedule 11.01.2016
comment
привет, @JoshuaShoemaker получение дочерних объектов возможно с помощью параметра запроса deep=true. Использование дипа возможно только для одного элемента, реализующего ленивую загрузку. После того, как вы получите список элементов, просто вызовите API /1/objects/items/1?deep=true, и вы получите все данные.   -  person Itay    schedule 13.01.2016


Ответы (1)


Как сказано в комментариях, не рекомендуется вызывать функцию, которая будет получать данные с сервера внутри представления, потому что она будет вызываться несколько раз, когда вам нужно, чтобы она вызывалась только один раз.

Вы можете добавить свойство «artistName», которое будет установлено в конструкторе «featuredAlbum».

owlyfm.controller('featuredAlbumController', [ "$scope","$http",function ($scope, $http) { $http.get("https://api.backand.com:443/1/objects/Artists/" + $scope.artistId) .success(function(result){ $scope.artistName = result.name; }); }]);

Итак, $http будет вызываться только один раз, при первом запуске контроллера.

person Ygalbel    schedule 24.01.2016