Javascript 导致递归深度错误的角度自定义过滤器

Javascript 导致递归深度错误的角度自定义过滤器,javascript,angularjs,filter,Javascript,Angularjs,Filter,在我的Angular应用程序中,我有一个名为listing.desired_majors的字段,它是一个主ID数组,例如:[3,20,24] 这些ID指的是我拥有的大学专业模型的主键。我试图用Angular编写一个过滤器,通过迭代数组并使用majors服务工厂请求每个major的标题,将ID数组转换为major的标题数组。请注意,这只需要发生一次,此处筛选的数据在页面呈现后将永远不会更新 然而,当我在模板中包含过滤器时,我会得到一个无限的递归错误,我不知道为什么。特别奇怪的是,它不仅抛出了一个深

在我的Angular应用程序中,我有一个名为listing.desired_majors的字段,它是一个主ID数组,例如:[3,20,24]

这些ID指的是我拥有的大学专业模型的主键。我试图用Angular编写一个过滤器,通过迭代数组并使用majors服务工厂请求每个major的标题,将ID数组转换为major的标题数组。请注意,这只需要发生一次,此处筛选的数据在页面呈现后将永远不会更新

然而,当我在模板中包含过滤器时,我会得到一个无限的递归错误,我不知道为什么。特别奇怪的是,它不仅抛出了一个深度错误,而且浏览器继续一次又一次地抛出这个错误,直到崩溃。现在,我已经重构了这个过滤器四五次,并且尝试了在堆栈溢出中包含一个bind-once指令,但是这也没有帮助。你能告诉我这里有什么问题吗?是因为数据是使用{{}绑定的,所以Angular不断地反复调用过滤器吗?如果这就是问题所在,为什么会导致深度错误

模板:

以下是joinBy筛选器供参考:

这是咖啡脚本 角度。模块'campusJobApp'。过滤器'joinBy',-> 输入,分隔符->输入| |[]。连接分隔符| |',' 下面是错误的屏幕截图。请记住,在浏览器崩溃之前,此错误会出现数百次:

您不能在每次调用过滤器时从过滤器返回包含新对象的列表。这将导致无限的摘要。您需要缓存转换后的列表,然后对转换后的数据进行筛选。例如,迭代原始数组,变换每个项,并将其存储在另一个数组中,并在本地缓存它,以便下次调用它时使用相同的变换数组。在您的过滤逻辑中,过滤转换后的数组而不是原始数组,这是有意义的,并证实了我的怀疑,即我试图做的是不可能的,但现在我知道了原因。如果您提交作为答复,我将接受。这可能是可能的,我不知道您如何使用过滤器的完整背景。在筛选器中添加“track by”实际上可能会解决此问题,因为它将不再依赖引用相等性来确定某个项是否已更改。换句话说,使用track by可能允许您在筛选列表中拥有新实例,而不会将其视为该项已更改。如果你发布一个简化的提琴,并将其添加到你原来的帖子中,它可能会有助于回答问题。
<dd ng-show="listing.desired_majors">{{ listing.desired_majors | majorIdsToObjects:'title' | joinBy:','}}</dd>
angular.module('myApp')
    .filter('majorIdsToobjects', ['majors', function (majors) {
        return function (items, returnAttr) {
            var filtered = [];

            var getMajor = function (major) {
                majors.get({majorId: major},
                    function (res) {
                        if (returnAttr == null) {
                            filtered.push(res);
                        } else {
                            filtered.push(res[returnAttr]);
                        }
                    }, function (res) {
                        //TODO: handle error
                    });
            };

            angular.forEach(items, function (item) {
                getMajor(item);
            });

            return filtered;
        }
    }]);