How to set the throttle parameter in ngInfiniteScroll (AngularJS)

1.1k views Asked by At

In my Angular application I am using the ng-infinite-scroll to allow a user to continously scroll through their 'news feed' using the plugin here - https://sroze.github.io/ngInfiniteScroll/documentation.html

On my desktop it runs fine, however when running this inside a Cordova app on an Android device the infinite scrolling uses a lot of CPU resources. I am trying to use the THROTTLE_MILLISECONDS option to only process scroll events every x seconds (this should increase performance and make scrolling less jerky).

I have my modules defined as follows:

var abcdDirectives = angular.module('abcdDirectives', []);
var abcdServices = angular.module('abcdServices', [ 'ngResource', 'infinite-scroll', 'ngCookies']);

abcdApp.value('THROTTLE_MILLISECONDS', 10000);

I am trying to throttle this as follows using the line above but it doesn't seem to make any difference.

In my template view I have the following code :

<div 
  infinite-scroll="tabs[tabIndex].FeedService.loadFeed(false, tabs[tabIndex].FeedService.filters, search.text, search.dateFrom, search.dateTo)"
  infinite-scroll-disabled="tabs[tabIndex].FeedService.busy || tabs[tabIndex].FeedService.noMoreResults || !tabs[tabIndex].active || tabs[tabIndex].FeedService.initialLoad"
  infinite-scroll-distance="1"
  infinite-scroll-immediate-check="false" >
<div ng-repeat="interaction in getTabItems(tabIndex) track by $index">

Within the js controller here is my getTabItems function

$scope.getTabItems = function (index) {
    if (angular.isDefined($scope.tabs[index].FeedService)) {
        console.log('getTabItems'); // this is being output to the console log over and over again extremely quickly
        return $scope.tabs[index].FeedService.items;
    }
}

The console log in the function above I can see in the console log is being output over and over again far too much & I am trying to throttle this function getting called but the throttle statement I have used seems to make no difference? What I am doing wrong with the code

-- Versions --

Angular 1.3.0 ng-infinite-scroll 1.2.2

1

There are 1 answers

0
kgfaith On BEST ANSWER

THROTTLE_MILLISECONDS should be set on the module which will use ngInfiniteScroll. So for your case, it should be set on abcdServices, like this.

var abcdDirectives = angular.module('abcdDirectives', []);
var abcdServices = angular.module('abcdServices', [ 'ngResource', 'infinite-scroll', 'ngCookies']);

abcdServices.value('THROTTLE_MILLISECONDS', 10000);

But in my opinion, value should be with it's direct parent(which use ngInfiniteScroll). Like this.

angular.module('yourApp.controllers', [])
.value('THROTTLE_MILLISECONDS', 5000)
.controller('controllerWhichUseInfiniteScroll',
['$scope',
    function ($scope) {
    }
]);

infinite-scroll event function(tabs[tabIndex].FeedService.loadFeed in your case) will be running in infinite loop if you set infinite-scroll-disabled flag to true before rendering new results of tabs[tabIndex].FeedService.loadFeed is finished.

To Fix the issue, set infinite-scroll-disabled flag to true in next digest loop using $timeout. That means flag will be true only when rendering results is finished. See below...

<div 
  infinite-scroll="getDataFromApi()"
  infinite-scroll-disabled="loaded"
  infinite-scroll-distance="1">
    <div ng-repeat="data in dataList">

--

angular.module('yourApp.controllers')
.controller('yourController',
['$scope', '$timeout', 'apiDataService',
    function ($scope,  $timeout, apiDataService) {
        $scope.dataList = [];

        $scope.getDataFromApi = function () {
            $scope.loaded = false;
            apiDataService.getData()
                .then(function(result) {
                    $scope.dataList = result.data;

                    //Set loaded to true after rendering new results is finished.Otherwise it will make infinite api calls.
                    $timeout(function (){
                        $scope.loaded = true;
                    });
                });
        }
    }
]);

Also worth pointing out that, getTabItems() should not be used to bind data in html for performance reason. Because angular will put it in digest loop for change detection and will be invoked lots and lots regardless of whether you use ngInfiniteScroll or not.