AngularJS承诺并使用自定义过滤器计时

AngularJS承诺并使用自定义过滤器计时,angularjs,filter,timing,promise,Angularjs,Filter,Timing,Promise,关于定制过滤器的计时,我现在非常头疼。 我有一个演示(学习角度)画廊应用程序,其中我使用带有复选框的自定义过滤器来选择不同类别的照片 Simptoms:当在ng repeat指令上使用自定义过滤器时,我注意到。。。经过几个小时的调试,我得出结论,问题是当过滤器运行时,JSON中的数据不在那里,尽管没有过滤器,一切似乎都正常加载 这里有一个用于此的plnkr(我复制粘贴了代码,对其进行了一点修改,尚未工作,将在早上修复它,但这是代码) 我开始在我的服务中使用延迟和承诺来获取JSON数据,这样控制器

关于定制过滤器的计时,我现在非常头疼。 我有一个演示(学习角度)画廊应用程序,其中我使用带有复选框的自定义过滤器来选择不同类别的照片

Simptoms:当在ng repeat指令上使用自定义过滤器时,我注意到。。。经过几个小时的调试,我得出结论,问题是当过滤器运行时,JSON中的数据不在那里,尽管没有过滤器,一切似乎都正常加载

这里有一个用于此的plnkr(我复制粘贴了代码,对其进行了一点修改,尚未工作,将在早上修复它,但这是代码)

我开始在我的服务中使用延迟和承诺来获取JSON数据,这样控制器和其他所有人都会等待数据加载,就像这样[services]

angular.module('services', []).factory('getAllPosts', ['$http', '$q', '$timeout',
function($http, $q, $timeout) {
  //defining the promised based API
  var deffered = $q.defer();
  //the getData function
  var getData = function() {
    //defining a empty data array
    var theData = {};
    //using $http to get the dat
    $http.get('/wordpress/api/get_recent_posts/').success(function(data) {
      // prepare data here
      //assigning our data to the theData array.
      // // New stuff here, we are pushing the data one by one to populate the array faster so it isn't emtpy .. ?!
      theData.length = 0;
      for (var i = 0; i < data.length; i++) {
        theData.push(data[i]);
      }
      theData = data;
    });
    //setting a timeout for the data and waiting if necesarry.
    $timeout(function() {
      deffered.resolve(theData);
    }, 1000);
    //when it s done, return the promise... i think so. ?!
    return deffered.promise;
  }
  return {
    //creating a getData handler to use in controllers.
    getData: getData
  };
}])
我正在使用getData().then()在加载时获取它

我意识到我没有对过滤器说同样的话

angular.module('filters', [])
.filter('checkboxFilter', function($filter) {
    return function(post, prefs) {
        var i, j, k, n, out, matchingpost = [];
        // loop through the post
        for (i = 0; i < post.length; i++) {
            console.log('I passed the length ... wtf?')
            out = false;
            n = 0;

            if (prefs) {
                // for each item, loop through the checkboxes categories
                for (j = 0; j < prefs.length; j++) {

                    // for each category, loop through the checkboxes categories of the current category
                    for (k = 0; k < prefs[j].categories.length; k++) {

                        // test if the current item property name is the same as the filter name
                        if (post[i][prefs[j].slug] === prefs[j].categories[k].slug) {

                            // test if checkbox is checked for this property 
                            (prefs[j].categories[k].value) ? n++ : out = true;
                            break;
                        }
                    }
                    if (out) break;
                    // if one filter in each categories is true, add item to the matchingpost
                    if (n === prefs.length) {
                        matchingpost.push(post[i]);
                    }
                }
            }
        }
        return matchingpost;
    }
})
angular.module('filters',[])
.filter('checkboxFilter',函数($filter){
返回函数(post、prefs){
变量i,j,k,n,out,matchingpost=[];
//在柱子上绕圈子
对于(i=0;i
问题是我开始读一本有棱角的书,但我不懂很多东西,所以我开始亲身体验,慢慢地每一点都到位了,但这一点。。。我花了很多时间在这上面。我想如果我再接下去,会更有意义


问题:如何消除这些错误并使筛选器在加载数据后读取数据


附带问题:通过一个不同的服务,我输出我主干网(Wordpress)中的所有现有类别,并在复选框中重复它们,我将如何将复选框链接到此过滤器的结果?(这对我来说还不明显,尽管我已经看到了一些例子……)


旁白2:为什么我所有的请求都会成倍增加,就像我发布的第一个屏幕截图一样,不,等等,这就是我要说的部分。。。到目前为止,我只有44篇帖子,但看起来即使数据已经存在,过滤器也会再次调用它

这种行为也发生在其他事情上。。。我想知道我做错了什么


注释:我正在使用angular 1.2.0rc1,从今晚开始,所有行为都出现在我使用的其他版本中:1.0.7.0、1.1.5

//defining a empty data array
var theData = {};
这是一个对象定义,不是数组定义。试着用

var theData = [];

这可能会解决您的问题。

无需创建您自己的承诺,因为AngularJS
$http
服务已经为您提供了这一功能

因此,您的服务可以简化为:

angular.module('services', []).factory('getAllPosts', ['$http', function($http) {
    return {
        getData: function() {

            // Return the promise that is created by the $http service
            return $http.get('/wordpress/api/get_recent_posts/')
        }
    };
}]);
<li ng-repeat="item in items">
    {{item.someProperty}}
</li>
然后在控制器中:

angular.module('yourModule')
.controller('ListController', ['$scope', 'getAllPosts',
    function($scope, getAllPosts) {

        $scope.items = []; // Placeholder for the data

        getAllPosts.getData()
            .success(function(data, status, header, config){

                 // Fill placeholder with data as soon as it is received
                 $scope.items = data;
            });
    }
]);
然后在您的视图中,您可以使用
ng model
指令或
ng repeat
指令如下所示显示数据:

angular.module('services', []).factory('getAllPosts', ['$http', function($http) {
    return {
        getData: function() {

            // Return the promise that is created by the $http service
            return $http.get('/wordpress/api/get_recent_posts/')
        }
    };
}]);
<li ng-repeat="item in items">
    {{item.someProperty}}
</li>
  • {{item.someProperty}
  • 如果要应用自定义筛选器,只需使用:

    <li ng-repeat="item in items | your_filter">
        {{item.someProperty}}
    </li>
    
  • {{item.someProperty}
  • AngularJS将在更新
    $scope.items
    时自动更新视图,因此您无需为此编写额外的代码


    希望有帮助

    解决这个问题的方法似乎是在信息到达之前循环。任何其他解决方案都是受欢迎的

    像这样:

    .filter('checkboxFilter', function() {
        return function(post, prefs) {
            //define empty vars, strict mode
            var i, j, k, n, out, matchingpost = [];
            //check to see if the posts have arrived
            if (post == undefined) {
                //posts are not here yet            
            } else {
                //posts have arrived.
                //iterate through all the posts
                for (i = 0; i < post.length; i++) {
                    out = false;
                    n = 0;
                    var eachPostCategories = post[i].categories;
                    //console.log(eachPostCategories)
                    for (j = 0; j < eachPostCategories.length; j++) {
                        //console.log(' post categories are');
                        //console.log(eachPostCategories[j]);
                        if (prefs == undefined) {
                            //preferences aren't in yet
                        } else {
                            //preferences are here.
                            //now we should iterate through all the preferences and compare them to the posts.
                            for (k = 0; k < prefs.length; k++) {
                                //prefs[j].slug
                                //console.log('categories are');
                                //console.log(prefs[k].slug)
                                if (eachPostCategories[j].slug === prefs[k].slug) {
                                    //console.log('this post has the categories');
                                    //console.log(post[i]);
    
                                    //WHAT DOES THIS LINE MEAN?
                                    /*(prefs[k].slug) ? n++ : out = true;
                                    break;*/
                                    n++
                                } else {
                                    out = true;
                                    break;
                                }
                                console.log('n is ' + n);
                            }
                            if (out) break;
                            // if one filter in each categories is true, add item to the matchingpost
                            if (n === prefs.length) {
                                matchingpost.push(post[i]);
                            }
    
                        }
                    }
    
                }
            }
            if (matchingpost.length == 0) {
                //return matchingpost = post
            } else {
                return matchingpost;
            }
    
        }
    })
    

    要发布具有多个类别的对象(例如,后期缩放的房屋具有日期、建筑类别)

    我认为真正的方法是覆盖默认的
    $interpolateProvider
    ,以启用返回承诺的过滤器。这样,您就可以推迟某些过滤表达式的呈现,直到它们被解析

    但是,请记住,对于链式过滤器,您不能简单地执行此操作。您可能还将被迫重写
    $parse
    ,以支持承诺链

    我现在面临着同样的问题,因此,我可能会继续这样做。如果是这样,我将确保在github存储库中为我的项目()发布一个指向答案的链接

    编辑

    另一种(大部分)简单的方法是将任意参数传递给过滤器,并通过HTTP调用(或任何其他方式)进行更新:

    在这里,我刚刚通过超时更新了结果,但我不必这样做。这只是为了示范。您可以选择任何方式更新
    $scope.result

    这是一个示例过滤器,它只会在结果中包含偶数:

    .filter('even', function () {
        return function (input) {
            if (!angular.isArray(input)) {
                return input;
            }
            var result = [];
            angular.forEach(input, function (x) {
                if (x % 2 == 0) {
                    result.push(x);
                }
            });
            return result;
        }
    });
    
    现在,在我看来,我可以通过以下方式将它们结合使用:

    <div ng-controller="MyController">
        <ul ng-if="result.length"> <!-- It is nice to not pollute the DOM with empty lists -->
            <li ng-repeat="item in result | even">{{item}}</li>
        </ul>
    </div>
    
    
    
      <div ng-controller="MyController"> <ul ng-if="result.length"> <!-- It is nice to not pollute the DOM with empty lists --> <li ng-repeat="item in result | even">{{item}}</li> </ul> </div>
    app.filter('translate', function() {
            return function(input) {
                try {
                    var index = input.toUpperCase();
                    if (app.translation[index]) {
                        if (input[0] === index[0])
                            return app.translation[index].capitalize();
                        return app.translation[index];
                    }
                    return input;
                }
                catch(err) {
                     throw "Translation not loaded yet, trying again...";
                }
            };
        })
    app.run(function($http) {
            $http.get("translations/" + "NB_ENG" + ".json", {
                    cache: true
                }).success(function(data) {         
                    app.translation = data;
                    console.info("Translation loaded.");
                }).error(function(q,w,e) {
                    app.translation = 1;
                    console.error("Failed getting translation: "+q + " | " + w + " | " + e + " | ");
                });
        });