【问题标题】:AngularJS Server Side Pagination - Recursively call APIAngularJS 服务器端分页 - 递归调用 API
【发布时间】:2015-03-04 05:30:13
【问题描述】:

我正在尝试调用一个接受参数 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 响应可能包含一个“下一个”链接,如果存在更多数据,该链接将为我提供调用 URL 以获取下一组数据...这就是分页的工作方式。

执行此操作并将返回的所有数据连接到一个 JSON 响应中的最佳方法是什么?

【问题讨论】:

  • 不要缓存您的get 请求,并在handleSuccess 和/或handleError 中再次使用正确的参数调用getData
  • 如何连接结果呢? @J.威尔斯
  • 我添加了我目前在 handleSuccess() 中的代码
  • 您只需连接到您的模型。您的模型应该已经包含最后检索到的结果。当新结果出来时,myThing.myCollection = myThing.myCollection.concat(newResults);
  • 另外,您的if (!!response.data) 可以是if (response.data)。没有理由将 response.data 的真实性转换为该评估的布尔值。

标签: javascript jquery angularjs pagination


【解决方案1】:

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

【讨论】:

  • 如何在我的 handleSuccess() 回调中获取“上一页数据”?我似乎只能访问当前数据,无法将数据保存在全局变量中。
  • 这是理解范围的问题,您需要访问范围之外的变量。阅读它是了解更多信息的最佳方式。
【解决方案2】:

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

首先,我将设置您的应用程序的服务层,以便所有被请求的对象都具有通用的通用方法(我强烈建议您使用 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();
        });

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-10
    • 2015-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-10
    相关资源
    最近更新 更多