对$ scope的需求感到困惑。$ apply

时间:2016-01-28 21:06:49

标签: angularjs

我有一个角度控制器:

.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;
            });

    };
});

Auth服务正在使用Cordova插件,该插件位于角度世界之外。我想我不清楚何时需要使用$scope.$apply更新您的$范围以及何时不需要。我的错误假设是因为我已将逻辑包装到角度服务中,然后在这个实例中我不需要它,但除非我将$scope.userInfo =语句包装在$timeout或{ {1}}。

为什么在这种情况下有必要?

2 个答案:

答案 0 :(得分:5)

来自angular's wiki

  

AngularJS为常见的本机JS异步行为提供包装器:

     

...

     

jQuery.ajax()=> $ HTTP

     

这只是带有$ scope的传统异步函数。$ apply()   最后调用,告诉AngularJS一个异步事件   发生。

所以我想因为您的Auth服务不使用角度$http,因此在执行异步$scope.$apply()后,Auth不会被角度调用功能

  

尽可能使用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();
});

答案 1 :(得分:2)

Angular不知道$scope.userInfo已被修改,因此需要通过使用$scope.$apply将更改应用于$scope来执行摘要周期。

是的,$timeout也会触发摘要周期。只有setTimeout的Angular版本才会在运行包装代码后执行$scope.$apply

在您的情况下,$scope.$apply()就足够了。

注意:$timeout也有异常处理并返回一个承诺。