什么是$ scope。使用Angular处理对象/数组所需的$ apply?

时间:2014-06-18 21:16:32

标签: 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){
     $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");         
        });
  }

3 个答案:

答案 0 :(得分:11)

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

如果您不知道$ digest周期是什么,那么这个概念很简单。在$ digest阶段,angular将对使用$ watch处理程序设置的每个范围变量进行脏检查,并检查它是否已更改;如果它有角度将调用其相应的$ watch处理程序来更新视图。

回到最初的问题 - 当angular知道您的代码时,它会为您触发$ digest循环 - 因此无需显式调用$ apply。如果你处理一个jquery事件,这是一个不同的故事。 Angular不知道可能需要$ digest - 它怎么样?因此需要$ apply来手动触发$ digest。

答案 1 :(得分:1)

我知道您已经收到了对您问题的正确答复。我想我也会提到使用$ 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);
    }

答案 2 :(得分:0)

Pixelbits的答案和an article by Jim Hoskins on $scope.$apply帮助我更好地理解了这一点。这是我原来问题的关键点:

  

那么,你什么时候需要调用$ apply()?实际上很少。   AngularJS实际上在$ apply中调用了几乎所有代码   呼叫。 ng-click,控制器初始化,$ http回调等事件   都包含在$ scope中。$ apply()。所以你不需要打电话   你自己,事实上你做不到。在$ apply内调用$ apply将会抛出   错误。

     

如果要在新的回合中运行代码,则需要使用它。和   仅当没有从AngularJS中的方法创建转弯时   库。在新的转弯中,您应该将代码包装进去   $范围。$适用()   (强调我的)

我仍然在转弯时朦胧但我得到的关键点是方法(在我的情况下为SC.get)不是AngularJS库的一部分因此我需要使用{{1} }。

(至少我想我明白了)