2016-01-28 109 views
4

我有一個角控制器:

.controller('DashCtrl', function($scope, Auth) { 
    $scope.login = function() { 
     Auth.login().then(function(result) { 
      $scope.userInfo = result; 
     }); 
    }; 
}); 

這是用我創建了一個服務:

.service('Auth', function($window) { 
    var authContext = $window.Microsoft.ADAL.AuthenticationContext(...); 

    this.login = function() { 
     return authContext.acquireTokenAsync(...) 
      .then(function(authResult) { 
       return authResult.userInfo; 
      }); 

    }; 
}); 

的驗證服務使用的是科爾多瓦的插件,將在角度世界之外。我想我不清楚何時需要使用$scope.$apply更新您的$範圍,以及何時不需要。我錯誤的假設是因爲我已經將邏輯封裝到一個角度服務中,因此在這種情況下我不需要它,但除非將$scope.userInfo =語句包裝到$timeout$scope.$apply中,否則沒有更新。

爲什麼在這種情況下有必要?

+0

可能的複製[AngularJS:Using scope。$ watch and scope。$ apply](http://stackoverflow.com/questions/15112584/angularjs-using-scope-watch-and-scope-apply) –

+0

'authContext.acquireTokenAsync(...)'使用'$ http'嗎? – Daniel

+0

@Daniel Nope。這是一個cordova插件,因此它將成爲一個爲Android應用程序調用本機java代碼的鉤子。 – Dismissile

回答

3

angular's wiki

AngularJS提供包裝,共同本地JS異步行爲:

...

jQuery.ajax()=> $ HTTP

這只是一個帶有$ scope的傳統異步函數$ apply() 在最後調用,告訴AngularJS發生了一個異步事件 。

,所以我想既然執行異步Auth功能後,您Auth服務不使用的角角的$http$scope.$apply()不叫。

只要有可能,請使用AngularJS服務而不是本機。如果你創建了一個AngularJS服務(例如套接字),它應該有一個 $ scope。$ apply()它觸發回調。

編輯:

在你的情況,你應該觸發digest cycle一旦模型被包裝更新(像你一樣):

Auth.login().then(function(result) { 
    $scope.$apply(function(){ 
     $scope.userInfo = result; 
    }); 
}); 

或者

Auth.login().then(function(result) { 
    $scope.userInfo = result; 
    $scope.$apply(); 
}); 
+0

建議是否在服務內部添加一個$ scope。$然後呢?而不必添加$ scope。$應用於所有使用該服務的控制器? – Dismissile

+0

我認爲,因爲實際的任務發生在控制器中,所以像這樣包裝'$ scope.userInfo ='語句(或者在它之後調用'$ scope。$ apply()')是最好的方法。否則在模型更新之前你可能會觸發'digest cycle'。 – Daniel

2

Angular不知道$scope.userInfo已被修改,所以需要通過使用$scope.$apply來執行摘要循環,以將更改應用於$scope

是的,$timeout也會觸發摘要循環。它只是在包裝代碼運行後執行$scope.$apply的角度版本setTimeout

在你的情況下,$scope.$apply()就足夠了。

注意:$timeout也有異常處理並返回一個承諾。