Angularjs 何时需要$scope.$apply来处理具有角度的对象/数组?

Angularjs 何时需要$scope.$apply来处理具有角度的对象/数组?,angularjs,angularjs-scope,soundcloud,Angularjs,Angularjs Scope,Soundcloud,我正在使用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)

我正在使用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 not defined)

我想更好地理解为什么需要
$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来手动触发$digest。

Pixelbits的回答帮助我更好地理解了这一点。以下是我最初问题的关键点:

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

如果要在新一轮中运行代码,您确实需要使用它。及 仅当该回合不是从AngularJS中的方法创建时 库。在新的回合中,您应该用 $scope.$apply() (强调矿山)

我仍然不清楚轮次,但我明白关键的一点是方法(
SC.get
,在我的例子中)不是AngularJS库的一部分,因此我需要使用
$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");         

        })
        }); 
  }

(至少我想我明白了)

我知道你的问题已经得到了正确的回答。我想我还应该提到,使用$http向SoundCloudAPI发出请求并不十分困难,因此您不需要使用$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);
    }

相当简单…您正在使用代码更新不属于angular的范围,因此它不知道如何运行摘要循环