AngularJS,爲何咱們要使用$apply()?在何時使用?

初學angular的時候,咱們在使用中常常遇到更改scope裏的值,可是model沒有相應的更新。因而咱們發現angular有一個$apply()方法,來update咱們的model.可是咱們使用事後,有時候控制檯會報出錯誤:html

Error: $digest / $apply already in progress。angularjs

而後咱們百度獲得的解決方案是:express

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

一直一來,我在我初學angular後作的項目裏也是這麼幹的。直到某一天我看到了有人說:
app

而後我開始反思,個人程序是是否是哪裏寫的有問題?在我翻看了不少大神的文章後,我大體理解了。函數

爲何咱們會使用到$apply()?oop

        通常狀況,咱們在 controller初始化、使用$http的callbacks、相似ng-click這類的ng-*事件時,angular都會用$apply()包起來當裏面的function或者一個Angular expression string執行後,就會去調用$scope.$digest()更新數據的綁定。因此是不須要你去主動調用$apply()的,且你在$apply()裏面調用$apply()將會拋錯的。就是如大家看到的$digest / $apply already in progressspa

        若是咱們用到了$apply()那麼應該是如下狀況:code

        a.  代碼處於$digest loop(更新週期)外,好比在"link"指令(directive)響應函數內部使用。也就是說,只能在$controller以外調用$apply,這樣它就能夠訪問到HTML或其餘控制器的聲明代碼 - 好比apply調用link指令並觸發相應功能,這時侯是確定在$digest loop以外的。htm

        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

相關文章
相關標籤/搜索