何时是$scope.$apply是用Angular处理对象/数组所必需的



我正在使用Soundcloud JS SDK,将我的Soundcloud收藏到一个简单的Angular应用程序中。

在使用$scope.$apply之前,我无法正确导入用户收藏夹。

function TopListCtrl($scope, $http, $modal) {
  $scope.getData = function(sc_user) {
     SC.get('/users/'+ sc_user +'/favorites', {limit: 200}, function(tracks){
     $scope.$apply(function() {
  if (Object.getOwnPropertyNames(tracks).length > 1) {
      $scope.likes = tracks;
      $scope.sortField = 'like.favoritings_count';
      $scope.reverse = true;
      $scope.sc_user = sc_user;
     } 
  else {
      alert("That user has 0 Soundcloud likes. So sad...")
     }
  }).error(function (data, status, headers, config) {          
             alert("Something went awry with that request. Double check that's a real Soundcloud username");         
        })
        }); 
  }

如果你不使用$scope。apply,它不起作用(并且说SC.get没有定义)。

我想更好地理解为什么$scope.$apply是必要的。我问这个问题是因为当我只是使用http api时,我不需要它。

function TopListCtrl($scope, $http, $modal) {
  $scope.getData = function(sc_user) {
     var url = 'http://api.soundcloud.com/users/'+ sc_user +'/favorites.json?client_id=0553ef1b721e4783feda4f4fe6611d04&limit=200&linked_partitioning=1&callback=JSON_CALLBACK';
    $http.jsonp(url).success(function(data) {
     if (Object.keys(data.collection).length > 0) {
      $scope.likes = data;
      $scope.sortField = 'like.favoritings_count';
      $scope.reverse = true;
      $scope.sc_user = sc_user;
     } 
    else {
      alert("That user has 0 Soundcloud likes. So sad...")
     }
  }).error(function (data, status, headers, config) {          
             alert("Something went awry with that request. Double check that's a real Soundcloud username");         
        });
  }

通常angular知道正在执行的代码因为你是提供函数回调的人但实际上是angular在调用它们。在angular调用一个函数之后,它会在稍后调用$apply来触发$digest循环。

如果你不知道$digest循环是什么,这个概念很简单。在$digest阶段,angular会对每个用$watch处理器设置的作用域变量进行脏检查,并检查它是否被修改了;如果有,angular会调用对应的$watch处理器来更新视图。

回到最初的问题——当angular知道你的代码时,它会为你触发一个$digest循环——所以没有必要显式地调用$apply。如果处理的是jquery事件,那就是另一回事了。Angular不知道可能需要一个$digest——它怎么知道呢?所以需要$apply来手动触发$摘要。

我知道你的问题已经得到了正确的答复。我想我还应该提到,使用$http向Soundcloud API发出请求并不是非常困难,所以你不需要使用$scope.$apply。以下是我的:

  var request = function(method, path, params, callback) {
    params.client_id = sc.soundcloud.client_id;
    params.oauth_token = sc.soundcloud.access_token;
    $http({
      method: method,
      url: sc.soundcloud.api.host + path,
      params: params
    })
    .success(callback);
  };
    get: function(path, params, callback) {
      request('GET', path, params, callback);
    },
    put: function(path, params, callback) {
      request('PUT', path, params, callback);
    },
    post: function(path, params, callback) {
      request('POST', path, params, callback);
    },
    delete: function(path, params, callback) {
      request('DELETE', path, params, callback);
    }

Pixelbits的回答和Jim Hoskins关于$scope的一篇文章。$apply帮助我更好地理解了这一点。以下是我最初问题的关键点:

那么,什么时候需要调用$apply()呢?实际上很少。AngularJS实际上在$apply中调用几乎所有的代码呼叫像ng-click、控制器初始化、$http回调等事件都封装在$scope.$apply()中。所以你不需要调用它你自己,其实你不能。在$apply内部调用$apply会抛出一个错误。

如果你要在新的回合中运行代码,你确实需要使用它。和仅当该转弯不是由AngularJS中的方法创建时才使用图书馆。在这个新转弯中,您应该将代码封装在范围。应用()美元(强调我的)

我仍然不清楚,但我得到的关键点是,方法(SC.get在我的情况下)不是AngularJS库的一部分,所以我,因此,需要使用$apply

(至少我认为我明白了)

最新更新