2017-07-18 4 views
0

問題なく再現できる小さなサンプルを作成しました。ファイルには、ブラウザでファイルをロードし、コンソールを開き

<!DOCTYPE html> 
<html ng-app='myApp'> 
    <head> 
    <meta charset="utf-8" /> 
    <script src="https://code.angularjs.org/1.6.5/angular.js"></script> 
    <script> 
    angular.module('myApp', []) 
    .filter('random', function() { 
     return function(input) { 

      var a = Math.floor(Math.random()*input.length); 
      var b = Math.floor(Math.random()*input.length); 
      return input.filter(function(element, i){ 
       if (i !== a && i !== b){ 
        return element; 
       } 
      }); 
     }; 
    }) 
    .controller('Controlleur', function($scope) { 
     $scope.contacts = [ 
      {"name": "donatello", "tel": 12456}, 
      {"name": "michaelangelo", "tel": 12456}, 
      {"name": "leonardo", "tel": 12456}, 
      {"name": "raphael", "tel": 12456}, 
      {"name": "robert", "tel": 12456}, 
     ] 
    }); 
    </script> 
</head> 
<body ng-controller="Controlleur"> 
    <ul> 
     <li ng-repeat="contact in contacts|random track by contact.name "> 
      <strong>{{contact.name}}</strong>: {{contact.tel}} 
     </li> 
    </ul> 
</body> 
</html> 

コピー/ペースト:それは配列からランダムに2要素を除去するフィルタです。あなたはF5を何回少数を打つ場合は、フィルタの作品を見ることができますが、あなたは、ランダムに取得します:

Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting! 
Watchers fired in the last 5 iterations: [[{"msg":"fn: regularInterceptedExpression","newVal":21,"oldVal":18},{"msg":"fn: regularInterceptedExpression","newVal":"raphael"},{"msg":"fn: regularInterceptedExpression","newVal":"12456"},{"msg":"fn: regularInterceptedExpression","newVal":"robert"},{"msg":"fn: regularInterceptedExpression","newVal":"12456"}], 
... 

問題は、それが通常$ダイジェストが連続して何回もトリガされた意味です。しかし、どこでも明示的にスコープを更新するわけではありません。私は単なるフィルターで新しい配列を作成しているだけで、明らかな副作用があります。

+0

連絡先を繰り返し処理し、同時にフィルタリングしています。これは、反復処理中の配列を変更することを意味します。角度がこの配列をループしていて、それが外出先で変化している場合は、おそらくあなたは問題に遭遇します。私はこの場所でフィルターを使用しません。 –

+0

私は配列を変更しません。 array.filter()は新しい配列を生成します。最初のものは変更されません。 –

答えて

2

ダイジェストごとにランダムなアイテムを返すので、スコープは決して安定しません(毎回同じ配列)。ダイジェストを探し続けると、それが安定するのを見て制限を打ち切り、中止します。

<li ng-repeat="contact in randomContacts track by contact.name "> 
    <strong>{{contact.name}}</strong>: {{contact.tel}} 
</li> 

DEMO

修正が表示およびビュー

.controller('Controlleur', function($scope, $filter) { 
    $scope.contacts = [ 
     {"name": "donatello", "tel": 12456}, 
     {"name": "michaelangelo", "tel": 12456}, 
     {"name": "leonardo", "tel": 12456}, 
     {"name": "raphael", "tel": 12456}, 
     {"name": "robert", "tel": 12456}, 
    ]; 

    $scope.randomContacts = $filter('random')($scope.contacts); 

}); 

ビュー内のランダムフィルタを除去するために、新しい濾過アレイを通過する前に一度ランダム化するために、コントローラに$filter()を使用することであろう

+0

範囲内で何も変更されていなくても、角で予防的に$ digestを数回実行しますか? –

+0

はい...ダイジェストサイクルで最低2回、スコープ全体をダーティチェックします。したがって、ビューロジックで生成されるランダムなものであれば問題が発生します – charlietfl

0

I実際には@ charlietflよりも優れた解決策が見つかりました。つまり、クロージャのフィルタレベルでランダムな結果をキャッシュし、代わりにランダムな結果をダイジェスト中に返します。とにかく$ intervalで行った新しいランダム値が必要なときにキャッシュをバストすることができます。

私は彼に「受け入れられた答え」の旗を聞かせました。

関連する問題