【问题标题】:What is best practices for syncing service cached Angular 1.3?同步服务缓存的 Angular 1.3 的最佳实践是什么?
【发布时间】:2016-07-15 16:38:55
【问题描述】:

我正在使用 Angular 1.3 处理一个遗留项目,并且一直在决定什么是在更新后保持服务变量和 $scope 同步的最佳方法,或者如果接收数据需要比摘要周期更长的时间。

我正在我的服务中实现变量缓存,它会为类似这样的变量返回一个 getter:

return function () {
            if(!this.games)
            {
                this.games= [];
                if(!!this.gameTypeId)
                    this.getAll(this.gameTypeId);
                else
                    this.getAll();
            };
            return this.games;
        }

如果 getAll 函数花费的时间比摘要周期长,则视图不会更新。因此,一种解决方法是使用 $apply,但感觉我以错误的方式处理这个问题。因为承诺看起来像这样:

return Resource.query({id: gameTypeId, resourceName: "Games/ByGameType"})
                    .$promise.then(function(response){
                        if(!$rootScope.$$phase) {
                            $rootScope.$apply(function () {
                                angular.extend(this.games, response);
                            });
                        }
                        else
                            angular.extend(this.games, response);
                    });

您必须检查 $digest 循环是否真的结束(如果承诺更快地返回值,则视图会自行更新)。

另一种方法是在控制器周围散布承诺返回并在那里更新 $scope.games,在这一侧控制器变得更加拥挤。而不是在 getter 中返回一个函数,而是返回一种将 $scope.games 重新绑定到 service->this.games 值的方法。第一种方法现在已经实现并且有效,但不确定它是否是最好的方法。

【问题讨论】:

    标签: javascript angularjs service


    【解决方案1】:

    这个

                        if(!$rootScope.$$phase) {
                            $rootScope.$apply(function () {
                                angular.extend(this.games, response);
                            });
                        }
    

    是不必要的安全设备。 Angular $q 承诺总是在摘要循环中执行。

    angular.extend 将通过组合新旧元素来破坏数组。除非这是要求,否则应该是

    angular.copy(this.games, response);
    

    【讨论】:

    • 我明白,this.games 总是会更新。问题是 $scope 并不总是反映这种变化。如果 $promise 在 $digest 主循环结束后更新,就会发生这种情况。之后,promise 只会更新 this.games 而不是 $scope。所以我使用 $apply 来更新视图,因为其中一个 $scope 变量设置为 getter。所以你建议通过控制器中的 promise.then() 更新 $scope 变量?顺便说一下,我写了一个简单的例子:plnkr.co/edit/uTp5KZ401YfnXJrlQg0E?p=preview
    • 您的示例不起作用,因为您使用了setTimeout。用 Angular 友好的($timeout,$http,resource)替换一个promise,它会的。您永远不需要在摘要期间触发摘要,并且您始终在 then 中进行摘要。
    • 对于只读模型 games 数组可能只是从模型返回并绑定到范围,就像原始代码应该做的那样(只要您使用 @ 保留对原始数组的引用987654329@)。对于读/写模型,getter 和 setter 很方便。
    • setTimout 仅用于模拟较长的响应时间。如果您将测试控制器中的 getter 函数替换为另一个函数(称为 longGameGetterFix),您会看到它工作正常。
    • @MattJ 这不是“修复”而是必需品。在setTimeout 中总是需要$apply,这就是为什么$timeout 是一个更短的替代方案(它也有利于测试)。您永远不需要在 $q 承诺中的 $timeoutthen 中使用 $apply。您永远不需要!$rootScope.$$phase 条件,因为它知道代码是否在摘要上运行。我想这是问题的一部分,所以这就是答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 2013-07-12
    • 2010-09-16
    • 2017-01-13
    • 2010-12-18
    相关资源
    最近更新 更多