Selectize报错:已达到10次$digest()迭代,请求排查解决
解决Selectize结合AngularJS过滤数组时的
10 $digest() iterations reached错误 问题场景
我在项目中使用Selectize下拉框:
<selectize config="mySelectizeConfig" options="getAvailableObjects(id)"></selectize>
控制器中直接返回数组时运行完全正常:
$scope.getAvailableObjects=function(id) { return $scope.available_objects[id] }
但一旦对数组做过滤处理,就会触发Error: 10 $digest() iterations reached. Aborting!的报错:
$scope.getAvailableObjects=function(id) { var result = []; result = $scope.available_objects[id].filter(function(object) { return object.is_active; }); return result; }
错误根源
AngularJS的脏值检测机制是靠对比值的引用地址来判断数据是否变化的。你每次调用filter方法,都会返回一个全新的数组对象——哪怕数组里的内容和上一次完全一样,Angular都会认为这个值发生了变化,于是会再次触发$digest循环去验证。这个过程会反复触发,直到达到框架设定的10次上限,就抛出了这个错误。
解决方案
下面给你几个实用的解决思路,按推荐程度排序:
方案1:缓存过滤后的结果(最推荐)
在控制器里维护一个缓存对象,只在源数据或者过滤条件变化时重新执行过滤,避免每次调用都生成新数组:
// 初始化缓存容器 $scope.filteredObjectsCache = {}; // 深度监听源数据变化,更新缓存 $scope.$watch('available_objects', function(newData) { if (!newData) return; // 遍历所有id对应的数组,预过滤并缓存结果 Object.keys(newData).forEach(function(id) { $scope.filteredObjectsCache[id] = newData[id].filter(function(item) { return item.is_active; }); }); }, true); // 第三个参数true表示深度监听对象内部的变化 // 修改方法直接返回缓存的结果 $scope.getAvailableObjects = function(id) { return $scope.filteredObjectsCache[id] || []; };
方案2:结合track by优化(视Selectize支持情况)
如果你的Selectize指令支持Angular的track by语法,可以在模板中添加这个规则,帮助Angular识别数组项的唯一性,减少不必要的脏检查:
<selectize config="mySelectizeConfig" options="item in getAvailableObjects(id) track by item.id"></selectize>
注意:这个方案的有效性取决于Selectize指令对Angular语法的兼容程度,如果指令内部没处理
track by,可能需要搭配方案1一起使用。
方案3:记忆化过滤函数
用记忆化(memoization)技术缓存相同输入的过滤结果,避免重复计算:
// 实现一个简单的记忆化工具函数 function memoize(func) { const cache = {}; return function(...args) { const key = JSON.stringify(args); if (!cache[key]) { cache[key] = func.apply(this, args); } return cache[key]; }; } // 把过滤函数包装成记忆化版本 $scope.getAvailableObjects = memoize(function(id) { if (!$scope.available_objects[id]) return []; return $scope.available_objects[id].filter(function(item) { return item.is_active; }); }); // 记得在源数据变化时清空缓存,保证数据更新 $scope.$watch('available_objects', function() { $scope.getAvailableObjects.cache = {}; }, true);
总结
核心问题就是每次过滤都生成新数组导致Angular脏检查陷入循环,只要让返回的数组引用在内容不变时保持一致,就能解决这个问题。优先推荐方案1,逻辑清晰且易于维护,适合绝大多数场景。
内容的提问来源于stack exchange,提问作者Petran
相关产品推荐
相关产品推荐

