AngularJS Server Side Pagination - 递归调用API

时间:2015-03-03 17:37:02

标签: javascript jquery angularjs pagination

我试图调用一个接受参数start和count的API,如下所示:

function handleSuccess() {
    if (!!response.data) {
            return (response.data);
        } else {
            return q.reject(response.data);
        }
}
function handleError() {
    // do some handling
}

function getData(url, sortBy) {

    var count = 10;
    var start = 1;

    var request = http({
            cache: true,
            method: "GET",
            url: url,
            params: {
                sortBy: sortBy,
                sortOrder: "ASC",
                count: count, // e.g. 10
                start: start  // e.g. 1

            }
        });
        return (request.then(handleSuccess, handleError));
}

来自API的JSON响应可能包含" next"链接,如果存在更多,将为我提供调用以获取下一组数据的URL ...这就是分页的工作方式。

最好的方法是什么,并将返回的所有数据连接到一个JSON响应中?

2 个答案:

答案 0 :(得分:0)

假设data响应的某些部分是一个数组,那么只需使用普通数组concat()将其与handleSuccess()回调中的前一页数据相结合。

答案 1 :(得分:0)

我发现,当尝试从同一端点获取分页数据时,面向服务的方式最有用,因为它很容易在控制器和指令之间共享服务和对象。

首先,我会设置你的应用程序的服务层,以便所有被请求的对象都有类似的通用方法(我强烈建议你使用ngResource或RESTAngular或类似的东西):

    angular.module('myModule')
        .factory('ApiObject', function($http, $q) {
            ApiObject = function ApiObject(attributes) {
                angular.extend(this, attributes);
            };

            ApiObject.query = function(url, parameters) {
                var deferred = $q.defer();
                $http.get(url, {params: parameters}).then(function(data) {
                    var results = [];
                    angular.forEach(data, function(apiObject) {
                        results.push(new ApiObject(apiObject));
                    });
                    deferred.resolve(results);
                }, function(error) {
                    // Do error stuff
                    deferred.reject(error);
                });

                return deferred.promise;
            };

            return ApiObject;
        });

然后设置服务来管理接受通用服务以及参数和配置选项的分页数据。还允许在服务中触发事件(请参阅triggeron方法),以便了解何时获取新结果。我也写了一些方法,将结果自动连接到当前结果集:

    angular.module('myModule')
        .factory('SearchService', function() {
            SearchService = function SearchService(service, params, config) {
                this.searchParams = params || {};
                this.config = config || {};
                this.service = service;
                this.results = [];
                this.listeners = {};
            };

            SearchService.prototype.fetch = function(params) {
                var _this = this;
                this.service.query().then(function(results) {
                    if(_this.config.concatResults) {
                        _this.results = _this.results.concat(results);
                       // You probably should make sure results are unique at this point as that is a common problem with paging a changing API
                    } else {
                        _this.results = results;
                    }

                    _this.trigger('searchSuccess', _this.results);
                });
            };

            SearchService.prototype.on = function(event, listener) {
                (this.listeners[event] = (this.listeners[event] || [])).push(listener);
            };

            SearchService.prototype.trigger = function(event, payload) {
                angular.forEach(this.listeners[event], function(listener) {
                    listener(payload);
                });
            };

            SearchService.prototype.isLastPage = function() {
                //logic here to determine last page
            };

            SearchService.prototype.nextPage = function() {
                if(this.isLastPage()) {
                    return;
                }
                if(this.searchParams.page) {
                    this.searchParams.page++;
                } else {
                    this.searchParams.page = 2;
                }

                this.fetch();
            };

            // Write more methods for previousPage, lastPage, firstPage, goToPage... etc.

            return SearchService;
        });

然后在您的控制器中,您将要使用一些默认参数和配置来实例化搜索服务,然后获取第一页:

   angular.module('myModule')
        .controller('MyCtrl', function($scope, ApiObject, SearchService) {
            $scope.searchService = new SearchService(ApiObject, {page: 1}, {concatResults: true});

            $scope.searchService.on('searchSuccess', function(results) {
                // Do something with results if you wish, but they'll already be stored in $scope.searchService
            });

            // Get the first page of data
            $scope.searchService.fetch();
        });

这显然是一个粗略的削减,有很大的改进空间,但我希望这将是一个很好的跳跃点,让你指向某种角度风格的方向。根据我的经验,这是从服务中的数据/请求层中抽象出分页逻辑的最佳方法。