【问题标题】:Angular Service/Factory undefined errorAngular 服务/工厂未定义错误
【发布时间】:2014-01-18 12:26:03
【问题描述】:

我建立了这个工厂服务:

spApp.factory('siteCollection', function(){
  return {
    usersObject : [],
    getUsers : function (){
      $().SPServices({
        operation: "GetUserCollectionFromSite",
        completefunc: function(xData, Status) {
          var responseXML = $(xData.responseXML);
          responseXML.find("User").each(function() {
            usersObject.push({
              id: $(this).attr("ID"),
              name: $(this).attr("Name"),
              domainAccount: $(this).attr("LoginName")
            });
          });
        }
      });
      return usersObject;
    }
  }
})

假设返回我在顶部声明的 usersObject,但控制台给我一个未定义的对象错误。

这是控制器:

spApp.controller('userCtrl', 
    function userCtrl($scope,siteCollection){
        $scope.users = siteCollection.getUsers();
    }
);

我对 Angular 还是很陌生。

【问题讨论】:

    标签: javascript angularjs angular-services


    【解决方案1】:

    您的代码有两个问题:

    第一个:您的工厂返回一个具有属性 usersObject 和 getUsers 的对象,但在 getUsers 中您尝试访问变量“usersObject”(它不是返回对象的属性)。你必须在外面声明变量:

    var usersObject = [];
    return {
      getUsers: function () {
        // ...
        return usersObject;
      }
    };
    

    第二个:你将你的 usersObject 填充到一个异步调用的回调函数中。 AngularJS 不会在您的数组中注册更改。您可以使用 $rootScope.$apply(),然后 AngularJS 将运行摘要并在新数据添加到数组后更新视图。

    spApp.factory('siteCollection', function ($rootScope) {
      // ...
      $rootScope.$apply(function () {
        responseXML.find("User").each( function () { ... } );
      });
    }
    

    使用 $rootScope.$apply() 不是很干净。更好的方法是返回一个承诺:

    spApp.factory('siteCollection', function ($q) {
      return {
        getUsers : function (){
          var deferred = $q.defer();
    
          $().SPServices({
            operation: "GetUserCollectionFromSite",
            completefunc: function(xData, Status) {
              var responseXML = $(xData.responseXML),
                  usersObject = [];
    
              responseXML.find("User").each(function() {
                usersObject.push({
                  id: $(this).attr("ID"),
                  name: $(this).attr("Name"),
                  domainAccount: $(this).attr("LoginName")
                });
              });
    
              deferred.resolve(usersObject);
            }
          });
    
          return deferred;
        }
      }
    });
    

    如果您决定使用 Promise,请将其添加到您的控制器中,以便在加载数据后执行某些操作:

    siteCollection.getUsers.then(function (users) {
      // ...
    });
    

    【讨论】:

    • 嘿,第一个更改解决了这个问题。但是,我真的不明白这里需要承诺。我正在使用 ng-repeat,它似乎正在工作。应许有什么帮助?谢谢。
    • 您使用外部库 (jQuery/SPServices) 从服务器加载数据。当这个过程异步运行时(我希望它这样做),脚本会继续运行,并且一旦加载数据就会执行你的回调。但是 Angular 不知道这个过程何时完成,因此它不会运行摘要循环,不会执行监视,更新视图等。当您使用承诺时,Angular 会在承诺的履行/拒绝处理程序执行后运行摘要循环.
    【解决方案2】:

    应该是这样的

    spApp.factory('siteCollection', function(){
      var usersObject = [];
      return {
        getUsers : function (){...
    

    您的返回是访问数据的方法的对象,但它们在范围上无关。所以如果只在返回对象中定义usersObject,在getUsers中是无法访问的。

    【讨论】:

      猜你喜欢
      • 2013-07-01
      • 2016-09-04
      • 2019-12-26
      • 2016-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多