2015-01-09 5 views
0

У меня есть простая функция контроллера, который подсчитывает, сколько ответов есть в каждом вопросе:AngularJS контроллер бесконечных запросы

$scope.countAnswers = function(questionid) { 
    AnswersQueries.getAnswers(questionid, function(answers) { 
    var answersCount = answers.length; 
    return answersCount; 
    }); 
}; 

HTML

<!-- Inside ng-repeat --> 
<div>{{countAnswers(question._id)}}</div> 

Сервис

angular.module('app') 
.factory('AnswersQueries', function ($resource) { 
    return { 

     getAnswers: function(questionId, callback) { 

     // Define resource 
     var data = $resource('api/answers?questionid=' + questionId); 

     // Fire the get call 
     data.query().$promise.then(function(answer){ 

      // Return answer in callback 
      callback(answer); 
     }); 
     } 
    }; 
}); 

И когда я попробуйте перезагрузить страницу, она делает TON запросов для подсчета вопросов ... правильных запросов, но никогда не останавливается:

т.е. ...

GET /api/answers?questionid=54ae02aec07933920b000001 200 28ms - 371b 
GET /api/answers?questionid=54aec71cdd9a29d210000001 200 28ms - 2b 
GET /api/answers?questionid=54aec75bdd9a29d210000002 200 32ms - 2b 
GET /api/answers?questionid=54adf9f0e0913a590a000001 200 7ms - 2b 
GET /api/answers?questionid=54ae02aec07933920b000001 200 14ms - 371b 
GET /api/answers?questionid=54aec71cdd9a29d210000001 200 4ms - 2b 
GET /api/answers?questionid=54aec75bdd9a29d210000002 200 4ms - 2b 
GET /api/answers?questionid=54aec75bdd9a29d210000002 200 15ms - 2b 
GET /api/answers?questionid=54ae02aec07933920b000001 200 18ms - 371b 
GET /api/answers?questionid=54aec71cdd9a29d210000001 200 17ms - 2b 
GET /api/answers?questionid=54adf9f0e0913a590a000001 200 20ms - 2b 
GET /api/answers?questionid=54ae02aec07933920b000001 200 17ms - 371b 
GET /api/answers?questionid=54adf9f0e0913a590a000001 200 7ms - 2b 
GET /api/answers?questionid=54aec71cdd9a29d210000001 200 9ms - 2b 

ошибка консоли (я думаю, что может решить проблему сейчас ... не видел этого раньше, потому что страница была замороженная):

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

Что могло произойти ?

+0

С помощью этой части кода, отображаемого в вопросе, как мы знаем, что на самом деле происходит? Вам не кажется, что вам нужно показывать минимальный код? – PSL

+0

Мне показалось, что я помню, что это было связано с «вопросом» внутри ng-repeat, но я добавлю больше кода, извините. –

+0

Должно ли 'countAnswers()' возвращать некоторое целочисленное значение? Но ваш код показывает, что функция ничего не возвращает. – tamakisquare

ответ

2

Я не уверен, помогает ли она решить проблему, но ваша функция countAnswers неверна.

Линия return answersCount; возвращается из функции обратного вызова. Ваша действительная функция countAnswers ничего не возвращает. Поскольку AnswersQueries.getAnwers является асинхронным, вы не можете использовать его результат немедленно.

Решение заключается в сохранении значений в области и обновлении в обратном вызове.

$scope.counts = {}; 
$scope.countAnswers = function(questionid) { 
    AnswersQueries.getAnswers(questionid, function(answers) { 
    $scope.counts[questionid] = answers.length; 
    }); 
}; 

//call $scope.countAnswers for each question in your scope *once* 

И HTML должен выглядеть следующим образом:

<div>{{counts[question._id]}}</div> 
0

Угловыми будет пытаться оценить каждое связывание каждый раз, когда он запускает цикл дайджеста. Существуют особые условия, которые автоматически запускают цикл дайджеста - одним из которых является получение ответа от $ resource (фактически $ http, используемого $ resource под капотом).

Ваш шаблон привязывается к выражению, которое вызывает функцию countAnswers, что делает новый запрос $ resource каждый раз при его вызове. Итак, когда приложение сначала переваривает, выполняется HTTP-вызов, и когда ответ получен, приложение снова переваривает и запускает другой http-вызов ... ad nauseum.

Одним из решений этой проблемы является кэширование результата HTTP-вызова, так что последующие вызовы «countAnswers» возвращают результат первого HTTP-вызова, а не делают другой HTTP-вызов.

Например:

var answersCounts = {}; 
var hasRequestedAnswers = {}; 
$scope.countAnswers = function(questionid) { 
    if (!hasRequestedAnswers[questionid]) { 
    AnswersQueries.getAnswers(questionid, function(answers) { 
     answersCounts[questionid] = answers.length; 
    }); 
    hasRequestedAnswers[questionid] = true; 
    } 
    return answersCounts[questionid]; 
}; 
Смежные вопросы