Как использовать Angular 1.6.5 вызов $http-запроса рекурсивно, когда возвращаемый набор данных ограничен

Я хотел бы использовать Angular 1.6.5 для перестройки проекта, но я не уверен, как использовать запрос $http.get на фабрике, когда источник возвращает только ограниченное количество записей за раз (1000 возвращается на запрос) и есть более 2000 записей, которые мне нужно получить.

В моем текущем коде я использую jquery ajax, а в методе.done проверяю наличие значения "__next", и, если оно существует, я вызываю функцию, передающую значение "__next". Когда значение "__next" не возвращается, я что-то делаю с данными.

function getSpecifiedList(url){

    var specUrl = url;

    $.ajax({
        url: specUrl,
        type: "GET",
        headers:{"accept":"application/json;odata=verbose",
          error: function(xhr){
            console.log(xhr.status + " " + xhr.statusText);
          }
        }
    }).done(function (results){
        $("#wc_report_holder").text(results.length);

        //buildObjects processes the results and adds to an array
        buildObject(results);
        if(results.d.__next){
            getSpecifiedList(results.d.__next);
        }else{
            buildGridView();
        }
    }).fail(function(error){
        $("#wc_report_holder").text("There was an error: " + error);
    });
}

Я хотел бы выяснить, как реализовать ту же проверку значений и рекурсивный вызов в angular 1.6.5, используя лучшие практики и наиболее эффективные, но мне не повезло, что я смог это выяснить на основе угловых документов и Google.

Вот краткая версия того, что я сейчас использую в Angular 1.6.5.

<script>
var sitesApp = angular.module("sitesApp", ['ngRoute']);

sitesApp.controller('SitesListCtrl', ['$scope', 'sites',
    function ($scope, sites) {
        sites.list().then(function (response) {
            $scope.sites = response.data.value;
        });
    }
]);

sitesApp.controller("SiteDetailsCtrl", ['$scope', '$routeParams', 'sites',
    function ($scope, $routeParams, sites) {
        sites.find($routeParams.SiteCodePc, function (site) {
            $scope.site = site;
        });
    }
]);


sitesApp.config(function ($routeProvider, $locationProvider) {
    $locationProvider.hashPrefix('!');
    $routeProvider.
        when('/', {
            templateUrl: 'https://machine/sites/site-list.html',
            controller: 'SitesListCtrl'
        }).
        when('/:SiteCodePc', {
            templateUrl: 'https://machine/sites/site-details.html',
            controller: 'SiteDetailsCtrl'
        }).
        otherwise({
            redirectTo: '/'
        });
});

sitesApp.factory('sites', ['$http', function ($http) {
    var urlBase = "https://some-endpoint-for-data";
    var cachedData;

    function getData(callback) {
        if (cachedData) {
            callback(cachedData);
        } else {
            return $http({
                method: 'GET',
                url: urlBase
            })
            .then(function (response) {
                //HERE IS WHERE I THINK THE SOLUTION NEEDS TO BE IMPLEMENTED
                cachedData = response;
                return cachedData;
            });
        }
    }

    return {
        list: getData,
        find: function (SiteCodePc, callback) {
            getData(function (response) {
                var site = response.data.value.filter(function (entry) {
                    //debugger;
                    return entry.SiteCodePc === SiteCodePc;
                });
                callback(site[0]);
            });
        }
    };
}]);

</script> 

<div ng-app="sitesApp">
    <div ng-view></div>
</div>

заранее спасибо

2 ответа

Похоже, вы можете сделать простую рекурсию, где вы принимаете второй (необязательный) параметр. Если вы вызываете getData() в первый раз, вы можете получить свои первые 1000 результатов. Однако, если вы найдете __next, то вы будете вызывать его снова, посылая текущие 1000 результатов, которые у вас есть, и сопоставлять следующие 1000 результатов с предыдущими 1000.

sitesApp.factory('sites', ['$http', function ($http) {
var urlBase = "https://some-endpoint-for-data";

function getData(callback, results) {
    return $http({
        method: 'GET',
        url: urlBase
    })
    .then(function (response) {
        // If you have found a previous batch of results then concat the two arrays
        if(results) {
            response = response.concat(results);
        }
        // If there are more results to be found then recursively call the same function passing the batched results
        if(response.__next) {
            return getData(callback, response);
        }
        // If there are no more results to be found then trigger your callback function
        else {
            callback(response);
        }
    });
}

return {
    list: getData,
    find: function (SiteCodePc, callback) {
        getData(function (response) {
            var site = response.data.value.filter(function (entry) {
                //debugger;
                return entry.SiteCodePc === SiteCodePc;
            });
            callback(site[0]);
        });
    }
 };
}]);

Я реализовал такой же сценарий с логикой пагинации и $ q. В этом примере кода я рекурсивно извлекаю записи как ленивые на основе LazyloadingLimit. Вы можете указать лимит на основе ваших требований. Таким образом, он извлекает записи только на основе количества из общего сбора. В этом примере ниже я не использую $ http. На вашем реальном примере вы можете использовать $http, чтобы получить записи с сервера. Здесь я просто жестко закодировал коллекцию изначально.

В вашем случае вы должны сначала получить общее количество записей и применить некоторую логику разбиения на страницы или какой-либо другой параметр для получения следующих записей.

angular.module('app', []);

angular.module('app').controller('SampleController', function ($scope,$http, $timeout, $q) {

    // $scope.initialize();
    $scope.mainCount = 0;
    $scope.lazyloadingLimit = 2;
    $scope.tileDefinitions = null;
    $scope.tempList = null;
    $scope.totalRecordCollection = [
        { "Name": "Record1" },
        { "Name": "Record2" },
        { "Name": "Record3" },
        { "Name": "Record4" },
        { "Name": "Record5" },
        { "Name": "Record6" },
        { "Name": "Record7" },


    ];
    function getTotalRecordCollection() {
        var deferred = $q.defer();
        deferred.resolve($scope.totalRecordCollection);
        return deferred.promise;
    }
    $scope.initialize = function () {
        debugger;
        var currentCount=0;
        var pageList = new Array();
        var currentPage = 1;
        var numberPerPage = 2;
        var numberOfPages = 0;
        function makeList() {
            numberOfPages = getNumberOfPages();
        }
        function getNumberOfPages() {
            return Math.ceil($scope.tempList.length / numberPerPage);
        }
        function nextPage() {
            currentPage += 1;
        } 
        function loadList() {
            var deferred = $q.defer();
            if (currentCount !== $scope.tempList.length) {

                var begin = ((currentPage - 1) * numberPerPage);
                var end = begin + numberPerPage;
                pageList = $scope.tempList.slice(begin, end);
                currentCount = currentCount + pageList.length;
                $scope.mainCount = currentCount;
                deferred.resolve(true);

            } else {
                debugger;
              return $q.reject();
            }
            return deferred.promise;

        }
        function loadNextRecords() {
            loadList().then(function (res) {
                nextPage();
                loadNextRecords();
            });
        }
        getTotalRecordCollection().then(function (response) {
            debugger;
            $scope.tempList = response;
            makeList();
            loadNextRecords();

        });

    }

});

 <body ng-controller="SampleController">
<input type="button" value="Click Here" ng-click="initialize()"/>
    {{mainCount}}
</body>

Как только все записи загружены, вы должны отклонить обещание, иначе рекурсивные циклы никогда не заканчиваются.

Надеюсь это поможет

Другие вопросы по тегам