AngularJS,为什么我们要使用$apply()?在什么时候使用?
AngularJS,为什么我们要使用$apply()?在什么时候使用?
随风所欲 发表于2年前
AngularJS,为什么我们要使用$apply()?在什么时候使用?
  • 发表于 2年前
  • 阅读 51
  • 收藏 1
  • 点赞 0
  • 评论 0

移动开发云端新模式探索实践 >>>   

摘要: 初学angular的时候,我们在使用中经常遇到更改scope里的值,但是model没有相应的更新。于是我们发现angular有一个$apply()方法,来update我们的model.但是我们使用过后,有时候控制台会报出错误:Error: $digest / $apply already in progress。然后我们百度得到的解决方案是:if(!$scope.$$phase) { //$digest or $apply }

初学angular的时候,我们在使用中经常遇到更改scope里的值,但是model没有相应的更新。于是我们发现angular有一个$apply()方法,来update我们的model.但是我们使用过后,有时候控制台会报出错误:

Error: $digest / $apply already in progress。

然后我们百度得到的解决方案是:

if(!$scope.$$phase) { 
    //$digest or $apply 
}

一直一来,我在我初学angular后做的项目里也是这么干的。直到某一天我看到了有人说:

然后我开始反思,我的程序是是不是哪里写的有问题?在我翻看了很多大神的文章后,我大致理解了。

为什么我们会使用到$apply()?

        一般情况,我们在 controller初始化、使用$http的callbacks、类似ng-click这类的ng-*事件时,angular都会用$apply()包起来当里面的function或者一个Angular expression string执行后,就会去调用$scope.$digest()更新数据的绑定。所以是不需要你去主动调用$apply()的,且你在$apply()里面调用$apply()将会抛错的。就是如你们看到的$digest / $apply already in progress

        如果我们用到了$apply()那么应该是以下情况:

        a.  代码处于$digest loop(更新周期)外,比如在"link"指令(directive)响应函数内部使用。也就是说,只能在$controller之外调用$apply,这样它就可以访问到HTML或其他控制器的声明代码 - 比如apply调用link指令并触发相应功能,这时侯是肯定在$digest loop之外的。

        b.  在你的代码块里面还包含有新的函数块,比如:

function Ctrl($scope) {
  $scope.message = "Waiting 2000ms for update";    
    setTimeout(function () {
        $scope.message = "Timeout called!";        
        // AngularJS unaware of update to $scope
    }, 2000);
}

    message在内部匿名函数内被赋值,是无法触发angular的脏值检测的,正确的做法就是:

function Ctrl($scope) {
  $scope.message = "Waiting 2000ms for update";    
    setTimeout(function () {
        $scope.$apply(function () {
            $scope.message = "Timeout called!";
        });
    }, 2000);
}

如何正确使用$apply()?

$scope.$apply()接收一个函数或Angular表达式字符串,并执行它,然后调用 $scope.$digest()来更新所有绑定或侦听者。

但有些人的做法是像我最初一样,直接使用

if(!$scope.$$phase) { 
    //$digest or $apply
}

这个做法就会导致如果你的代码出错,然后又没有相应的处理机制那么程序就会卡死在那里。

$apply不仅仅执行你的代码,它内部的try / catch语句让你的错误总是能被捕捉到,并且$digist是最后的保障,它意为着即使一个错误抛出,它仍能运行。所以正确的做法是:

$scope.$apply(function () {
    $scope.message = "Timeout called!";
});

以上是我观点,如有错误,请指证!

参看文章:AngularJS and scope.$apply

  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 1
博文 9
码字总数 7237
×
随风所欲
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: