AngularJS 将 lastTime 传递给服务以仅显示最近的帖子

AngularJS passing lastTime to a service to display only recent posts

我不确定我这样做是否正确,但我想要实现的是类似 Twitter 提要的效果。

我有一个状态页面,在第一个页面加载时它会获取所有状态,然后它只会在页面上显示更新。

我有一个调用 API:

的服务
emp.services.SocialService = ['$http', '$q', function ($http, $q) {

    var deferred = $q.defer();

    $http.get('/api/feed').then(function (data) {
        deferred.resolve(data);
    });

    this.getStatuses = function () {
        return deferred.promise;
    };

    return {
        getStatuses: this.getStatuses
    };

}];

还有我的控制器:

emp.controllers.StatusesController = ['SocialService', '$scope', '$interval',  function(SocialService, $scope, $interval) {

    $scope.statuses = [];
    $scope.lastTime = 0;

    $scope.refreshStatuses = function() {

        var statuses = SocialService.getStatuses();

        statuses.then(function(data) {

            $scope.statuses = data.data;

            for(id in $scope.statuses) {

                item = $scope.statuses[id];

            }

        });
    };

    $scope.periodicRefresh = function() {
        $scope.refreshStatuses();
        $interval($scope.periodicRefresh, dataInterval, true);
    };

    $scope.periodicRefresh();



}];

有人可以看看这个并告诉我如何改进它,只将更新推送到视图。我假设我还需要以某种方式将 lastTime 传递给 API URL 以便我可以使用它来仅获取任何更新,然后以某种方式将它们推送到视图?

非常感谢任何帮助、教程等。

构建服务时,尽量将所有 "service-related" 功能保留在服务范围内。这将有助于减少您的控制器在长期 运行 中的占用空间。此外,重要的是要了解 "promises" 默认情况下在整个 angular 框架中使用。在这种情况下,$http 服务已经 returns 承诺。

请在下方查看您的服务:

emp.services.SocialService = ['$http', function ($http) {

    var totalRefreshCount = 10,
        currentRefreshCount = 0;

    function getStatuses() {
        return $http.get('/api/feed');
    };

    function updateTotalRefreshCount() {
        currentRefreshCount = currentRefreshCount + 1;
        return currentRefreshCount;
    }

    function shouldRunAgain() {
        return totalRefreshCount >= currentRefreshCount;
    }

    function resetCounter() {
        currentRefreshCount = 0;
        return;
    }

    return {
        getStatuses: getStatuses,
        shouldRunAgain: shouldRunAgain,
        updateTotalRefreshCount: updateTotalRefreshCount,
        resetCounter: resetCounter
    };

}];

注意如何 "getStatuses" 只是 returns $http 方法?请注意我是如何开始在这里封装所有 "polling" and/or "recursion" 逻辑的。这指的是我原来的说法,"Try and keep all service-related code in our service scope".

请在下方检查您的控制器:

emp.controllers.StatusesController = ['SocialService', '$scope', '$timeout',  function(SocialService, $scope, $timeout) {

    var dataInterval = 1 // in seconds;

    $scope.statuses = [];

    $scope.refreshStatuses = function() {

        SocialService.getStatuses().then(function(data) {

            $scope.statuses = data.data;

        });

    };

    $scope.periodicRefresh = function() {

        $scope.refreshStatuses();

        if (!SocialService.shouldRunAgain())
            return;

        $timeout(function(){

            $scope.periodicRefresh();

            SocialService.updateTotalRefreshCount();

        }, dataInterval * 1000);

    };

    SocialService.resetCounter();
    $scope.periodicRefresh();

}];

您的代码使用了一些我不理解的变量。例如,"dataInterval" 和 "item"。它们被使用但从未被定义...

"refreshStatuses" 是相同的代码。它看起来与您之前拥有的几乎相同。它甚至可以与 "then" 方法一起使用。同样,由于 $http 已经返回承诺。

对于您的 "polling",不是创建间隔实例,而是执行超时。这是一种更合适的递归方法,因为您不会创建任何不必要的间隔循环。

最后,递归的所有逻辑(ig "how many times it should run" 和 "when should it stop")都保存在服务中。这是因为它与服务有关。

您还可以通过将 "periodic" 刷新移动到该服务来更进一步。同样,主要是因为它只是服务逻辑。

结果:

在 10 次尝试的过程中,您的 api/feed 将每 1 秒获取一次。

请检查存在未定义变量的区域。

Angular 将触发它的摘要循环。每次刷新 运行 秒时,您的状态都会更新。


编辑:为 API

添加时间戳
emp.services.SocialService = ['$http', function ($http) {

    var totalRefreshCount = 10,
        currentRefreshCount = 0,
        timeStamp = null;

    function getStatuses() {

        // generate query param
        var query = timeStamp === null ? "" : "?ts=" + timeStamp.toJSON();

        // update/create time stamp
        timeStamp = new Date();

        return $http.get('/api/feed' + query);
    }

    function updateTotalRefreshCount() {
        currentRefreshCount = currentRefreshCount + 1;
        return currentRefreshCount;
    }

    function shouldRunAgain() {

        if (totalRefreshCount >= currentRefreshCount) {
            updateTotalRefreshCount();
            return true;
        }

        return false;

    }

    function resetCounter() {
        currentRefreshCount = 0;
        timeStamp = null;
        return;
    }

    return {
        getStatuses: getStatuses,
        shouldRunAgain: shouldRunAgain,
        resetCounter: resetCounter
    };

}];
每当发出新请求时,

"getStatuses" 将包含一个时间戳查询参数。

我们的控制器只有轻微的变化:

emp.controllers.StatusesController = ['SocialService', '$scope', '$timeout',  function(SocialService, $scope, $timeout) {

    var dataInterval = 1 // in seconds;

    $scope.statuses = [];

    $scope.refreshStatuses = function() {

        SocialService.getStatuses().then(function(data) {

            // appends new array to existing.
            $scope.statuses.push.apply($scope.statuses, data.data);

        });

    };

    $scope.periodicRefresh = function() {

        $scope.refreshStatuses();

        if (!SocialService.shouldRunAgain())
            return;

        $timeout($scope.periodicRefresh(), dataInterval * 1000);

    };

    SocialService.resetCounter();
    $scope.periodicRefresh();


}];

这些小改动不会解决您所有的问题。您将需要依靠您的服务器来返回仅在时间戳之后创建的结果。