无法访问JavaScript对象属性

时间:2014-06-21 19:50:38

标签: javascript json angularjs

即使属性存在,我也无法访问JavaScript对象的属性。我试图访问AngularJS中的Factory对象的属性。以下是代码:

angular.module("appManager")

  // factories.js
  .factory("DataFactory", function ($http) {
    var fac = {};

    fac.expenses = {};
    $http.get("mvc/m/revenue.json")
        .success(function (result) {
            console.log(result);            // line 9
            fac.expenses = result.expenses;
        });
    console.log(fac);                       // line 13
    return fac;
  })

  // expenseController.js
  .controller("expenseCtrl", function($scope, DataFactory){
    $scope.data = DataFactory.expenses;
    console.log(DataFactory);               // line 4
    console.log(DataFactory.expenses);      // line 5
    console.log($scope.data);               // line 6

    // Global // var d = {};
    d = DataFactory;
    e = DataFactory.expenses;
  });

控制台中的输出: enter image description here

有人也问过(here)这个,但他没有得到解决方案。我也尝试了那里的建议:使用键,控制台抛出“未定义的函数”错误。您还可以注意到log() // 9内的日志$http比其他函数更晚调用;这可能是原因吗?但请注意log() // 13可以已经打印对象。

我认为AngularJS可能有问题,我尝试了一些全局变量d and e,用于测试目的,这也提供了相同的结果。

我也尝试了下标:DataFactory["expenses"],结果相同

有人可以告诉我我做错了吗?

2 个答案:

答案 0 :(得分:2)

您正在使用异步调用,但尝试将它们视为同步发生。当您最终尝试在网络调用之前尝试使用结果时,这根本不起作用,该网络调用请求结果实际已完成并已返回。

查看控制台语句的顺序。第13行($http.get())调用发生在第9行之前(在.success的{​​{1}}处理程序中)。因此,在第13行,我们无法分配$http.get()。甚至标记为第4,5,6行的那些也发生在第9行之后fac.expenses之前。

您似乎没有编写代码来处理异步网络呼叫,这就是它无法正常工作的原因。您只能在fac.expenses内或fac.expenses处理程序中调用的内容中可靠地使用.success handler

此外,由于这是与时间相关的问题,因此您可以通过调试工具以多种方式欺骗。通常,您应该记录您要查找的实际值,而不是父对象,因为.success在您稍后尝试钻入日志中的父对象时可能会让您感到困惑(因为它已被填充)在)。


我并不完全按照您在此处尝试实现的目标来确切知道要推荐什么,但如果您想使用console.log(),那么您必须在最初返回它的fac.expenses处理程序,或者您可以调用其他函数并将.success传递给其他函数。您无法像您正在做的那样从异步回调中返回它,并希望它可以在已经执行过的其他链式代码中使用。

答案 1 :(得分:1)

jfriend00击中了头上的钉子。您将从DataFactory服务返回一个空对象,然后从Ajax服务获取结果。异步调用的本质是您的代码继续运行,返回空对象,同时等待来自服务器的响应。 Async第一次遇到它时会咬人,但是你将来会认识到这种模式。

有一种现代的方法来处理这种称为延迟承诺的模式。 Angular中的$ q服务为您提供延迟对象。

https://docs.angularjs.org/api/ng/service/ $ Q

所以你使用$ q的服务看起来像这样:

 .factory("dataFactory", ['$http', '$q', function ($http, $q) {
     var fac = $q.defer();

     $http.get("mvc/m/revenue.json")
         .success(function (result) {
             fac.resolve(result);
         });                   
      return fac.promise;
 }]);

然后您的控制器看起来像

 .controller("expenseCtrl", ['$scope', 'dataFactory', function($scope, dataFactory){
    dataFatory.then(function(data) {
        $scope.data = data.expenses;
    });
 }]);