AngularJS控制器无限请求

时间:2015-01-09 02:30:11

标签: javascript 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);
        });
      }
  };
});

当我尝试重新加载页面时,会发出大量请求来计算问题...正确的请求,但它永远不会停止:

...即

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: []

可能会发生什么?

2 个答案:

答案 0 :(得分: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>

答案 1 :(得分:0)

Angular将在每次运行摘要周期时尝试评估每个绑定。有一些特定条件会自动触发摘要周期 - 其中一个是从$ resource接收响应(实际上是$ http,由引擎盖下的$ resource使用)。

您的模板绑定到一个调用函数countAnswers的表达式,该函数在每次调用时都会生成一个新的$ resource查询。因此,当应用程序首先进行摘要时,会进行http调用,并且当收到响应时,应用程序会再次摘要并启动另一个http调用... ad adause。

此问题的一个解决方案是缓存http调用的结果,以便后续调用&#39; countAnswers&#39;将返回第一个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];
};