【问题标题】:Angularjs does not update view on async model changesAngularjs 不会更新异步模型更改的视图
【发布时间】:2014-10-23 22:05:31
【问题描述】:

由于模型和视图之间缺乏同步,我在尝试将模型与控制器分开时遇到了问题。我环顾四周,发现大多数时候应用程序可以解决问题。但是, apply 对我根本不起作用(从根范围或使用 chrome 的相关范围调用时)。在这个link 中,我演示了我在程序中遇到的几乎所有问题,但是我的程序不是间隔,而是异步请求或者只是复杂的函数,这些函数似乎也被角度所遗漏。在演示中,我有 4 个变量应该在视图上得到更新。一个被范围监视,另一个通过回调更新,另一个完全依赖于模型,另一个通过将范围本身传递给服务来更新。在 4 个中,只有回调并将范围传递给服务是更新视图的,即使我在每次更新后运行 apply (在每次执行 $interval 后已经运行的那个之上)。我要避免的是每当我的数据由于转换而发生变化时使用大量的回调或承诺,因为我有许多不同的转换是可能的。无论如何要这样做还是回调和承诺是唯一的选择?

var test = angular.module("tpg",[]);
test.controller("myctrl", function($scope, $interval, service)
{
  $scope.$watch(service.list.name, function()
  {
    $scope.name=service.list.name;
  });

  $scope.op=service.list.op;

  $scope.call=service.list.call;

   $scope.scope=service.list.test;

  $scope.update=function()
  {
    service.getValues(function(op){$scope.op=op}, $scope);
  };
}).factory("service", function($interval, $rootScope)
{
  return {
    list:{name:"OPA", op:"TAN", call:"1", test:"scope"},
    getValues:function(callback, $scope)
    {
      var self=this;
       var interval = $interval(function()
        {
          if(self.count>2)
          {
            $interval.cancel(interval);
            self.count=0;
            self.list={name:"OPA", op:"TAN", call:"1"};
          }
          else
          {
            self.list=self.values[self.count];
            callback(self.list.op);
            $scope.scope=self.list.test;
            console.log(self.list);
            self.count++;
          }
          $rootScope.$$phase || $rootScope.$apply();
        },2000);


    },
    values: [{name:"guy", op:"ungly", call:"2", test:"scope1"}, {name:"TAL", op:"stink", call:"3", test:"scope2"}, {name:"tes", op:"test", call:"4", test:"scope3"}],
    count:0
  };
});

【问题讨论】:

    标签: javascript angularjs web frameworks


    【解决方案1】:

    您只需要从服务返回的回调函数。处理 Angular 服务时不需要 $scope.$apply,因为服务本身会触发摘要运行。所以我修改了代码以删除 $apply 和 promise,并从服务返回一个简单的回调,然后使用返回的数据更新视图。

    代码:

    $scope.update=function()
      {
        service.getValues(function(data){
          $scope.name = data.name;
          $scope.op=data.op;
    
        $scope.call=data.call;
    
       $scope.scope=data.test;
        });
      };
    }).factory("service", function($interval, $rootScope)
    {
      return {
        list:{name:"OPA", op:"TAN", call:"1", test:"scope"},
        getValues:function(callback){
          var self=this;
           var interval = $interval(function()
            {
              if(self.count>2)
              {
                $interval.cancel(interval);
                self.count=0;
                self.list={name:"OPA", op:"TAN", call:"1"};
              }
              else
              {
                self.list=self.values[self.count];
                console.log(self.list);
                callback(self.list);
                self.count++;
              }
            },2000);
        },
        values: [{name:"guy", op:"ungly", call:"2", test:"scope1"}, {name:"TAL", op:"stink", call:"3", test:"scope2"}, {name:"tes", op:"test", call:"4", test:"scope3"}],
        count:0
      };
    });
    

    Working plunkr

    【讨论】:

    • 听起来就是这样,我试图避免使用回调和承诺(我的控制器中已经有很多),但我真的没有看到好的替代方案。跨度>
    • 没错,无论如何这将是使用范围时的性能问题。$apply 仅在角度范围内时,因此首选回调和承诺
    • 我发现更好的解决方案是对依赖于变化的模型变量使用广播或监视。这样,当您有多个处理异步进程的方法时,就不需要到处进行回调了。我在 plunker 中的手表示例实际上是错误的,这就是它没有更新的原因。
    • $watch 将始终运行摘要,因此会影响性能。您在代码中的 $watchers 越多,您的应用程序就会越慢。
    猜你喜欢
    • 2014-02-13
    • 2013-12-02
    • 1970-01-01
    • 1970-01-01
    • 2012-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多