【问题标题】:how to parse a $resource object in angularJS如何在 angularJS 中解析 $resource 对象
【发布时间】:2015-11-02 17:14:28
【问题描述】:

我有一个烦人的问题需要帮助。 我有一个从雅虎股票中获取股票数据的控制器。控制器将数据存储在 $scope.stocks 中,在我看来,我可以使用 ng-repeat 显示数据,因此一切正常。当我尝试从数据的每个元素中提取一些数据时,问题就来了……它说对象是未定义的。 下面是我的控制器,负责获取。

    app.controller('controller2', ['$scope','$resource', function($scope, $resource){
    var URL='http://finance.yahoo.com/webservice/v1/symbols/allcurrencies/quote?format=json';
    $scope.stockAPI=$resource(URL, {callback: 'JSON_CALLBACK'},{get:{method:'JSONP'}});
    $scope.stocks=$scope.stockAPI.get({});
    console.log($scope.stocks);
    var temp=$scope.stocks.list.resources;  // this returns an error (TypeError: Cannot read property 'resources' of undefined)
    console.log(temp);

}]);

我使用这个控制器的视图如下所示(这个视图也显示了我想要的数据)

    <body ng-app="weatherApp" class="container">
    <div ng-controller="controller2" ng-model="buffer">
        <h1>This is the index page where the application is mounted</h1>
        <ul ng-repeat="stock in stocks.list.resources">
            <li>{{stock.resource.fields.name}}  {{stock.resource.fields.price}} {{buffer.push(stock.resource.fields.name)}}</li>
        </ul>
    </div>
</body>

我从控制器返回的 json 数据如下所示,视图可以很好地呈现它,但是我无法创建一个新列表,该列表仅包含每个元素中包含的众多字段中的三个字段对象...请帮助这让我沮丧了两天。

$promise: d

$resolved: 真

list: Object

 meta: Object

  resources: Array[173]

      [0 … 99]

      [100 … 172]

      length: 173

      __proto__: Array[0]

  __proto__: Object

原型:e

【问题讨论】:

    标签: javascript json angularjs angularjs-resource angularjs-http


    【解决方案1】:

    您应该传递一个函数,然后在该函数内设置$scope.stocks

    $scope.stockAPI.get({}, function(data){
       $scope.stocks = data;
    });
    

    否则您可以使用$promise,然后在您的.then 函数中更新$scope.stocks

    $scope.stockAPI.get().$promise.then(function(data){
       $scope.stocks = data;
    });
    

    【讨论】:

    • @BuyaNami 对你有帮助吗..?
    • Pankaj 感谢您的回复。我已经尝试了这两种方法,使用第二种方法 - 在回调函数中定义但未在控制器范围中定义的 $scope.stocks,因此当我 console.log($scope.stocks) 在 . then() 部分。在第一种方法中,我得到了一个 $scope.stocks 对象,但我无法解析它——console.log($scope.stocks.list) 返回未定义。
    • @BuyaNami 你不能在它的函数之外有异步调用响应..我们正在设置一个$scope.stocks 因为我们正在处理异步调用
    • e {$promise: d, $resolved: false} // 这是来自回调函数外部 app.js:58 // 这是来自回调函数内部,这个值不是在回调函数之外可用 [Object, Object, Object, Object, Object, Object, Object, Object, Object, Object…]
    • @BuyaNami 使用 debuggerdebug javascript 或使用 console.log(variableName) 然后按 f12 在控制台中查看值
    【解决方案2】:

    好的,问题解决了。 如果您遇到类似问题,这是如何解决的。 首先实现http调用是异步完成的,其次尝试使用服务来处理异步任务(或一般的本地数据仓库)。 所以让我们来看看细节;

    var app=angular.module('app',[]);
    app.service("DataService", function($http, $q){
    var defered=$q.defer();  // this is not for the HTTP delay... instead it is for populating our local Names and Lengths variables --defined below
    var buffer=[];  // I'm not sure if I need this anymore but It hold a promise as well
    var Names=[];  // these are the variables I'm interested in using, which I first need to populate them from an http call that I'll call later
    var Lengths=[];  // also this is a local variable that I want ( just for kicks)
    
    var url='http://www.w3schools.com/angular/customers.php'; // ofcourse our remote server API that responds with a jason full of data 
    // this function is called from inside our fetchdata method defined below this method, this function processes the data (from the http promise once successfull)--- it just parses through the json objects and isolates/groups similar data --- all the names go into a name array and the length of each name goes into a different array ( I want to make a D3 chart from it in the end) 
    var fixup= function(data){
        var records=data.records;  // records now contains an array of objects with few fields each
    
        records.forEach(function(record){
          console.log(record.Name+"  ----  "+record.Name.length); // taking a look/peak at the individual records fields 
          Names.push(record.Name); // store each record's name value in our local Names array
          Lengths.push(record.Name.length); // do something similar for the length of each name
        })
        defered.resolve(Names);// this is the main thing here-- you will send our local Names array once everything works out- i.e the data has arrived from the server and the loop is finished running processing the fetched data... when you return the promise (as we will see later) it will contain whatever we put the resolve as an argument so here it is Names array, it could be whatever you want
    } // so that is it for fixdup function
    // next is our fetching method
    var fetchData=function(){
        $http({             // this is an asynch call, it moves on to the next method once the call is made-- so you have no data still. 
            method: 'GET',
            url: url
        }).success(function(data){ // this is the next big deal here the promise (internally used by the http service) is processed here- if successful this function handles the response if not the next method handles the errors
            buffer=fixup(data);// give the data to our fixup function we saw above
        }).error(function(err, status){
            console.log(err);
        })
    }// so anyone that looks at buffer will not see anything unless the .then method of this promise object is invoked
    
    console.log('fetching data away we goooo....'); // lets us know where we are at the console logs
    fetchData(); // does the fetching business which calls the fixup method which calls defered.resolve() method.
    return defered.promise; // this will wait untill we're done with defered.resolve(Names) call... this returns a promise that we will have our names array sometime later
    
    });
    // here we are going to use our dataservice service we defined above... remember it will only five us something once the resolve(names) finishes running
    app.controller("controller1",['$scope', 'DataService', function($scope,  DataService){
    //$scope.myData=[];
    $scope.names=[];  // these guys are clue less about where their data is coming from, so they are just chilling here in the scope unaware of what's about to happen
    $scope.lengths=[]
    DataService   // kapow!! we call our get-us-some-data service happily named DataService ofcourse
    .then(function(names){ // so this function is fired up once we have names parameter available--- this is sent from the last call in the DataService service (return defered.promise) which as we discussed will only run when the resolve(Names) is done running  ... I know it sounds confusing but it will take you few tries to get a hung of it--- took me two long days to rap my mind about this asynch thing --- I'm too synch to a fault haha OK moving on
        console.log('back from DataService sendit service method'); // inspect our efforts here... first let us know where we are when we get an output on the console
        $scope.names=names; //  here is the magic... after all those promises and and back and forth method calling we end up with out own local scope names array exactly like we wanted and we can give this data to a D3 directive and everyone is happy
        console.log(names);
        })
    .then(function(names){ // we can chain promises and do other things here, I'm populating another local scope variable from the same promise returned... so we will not need to call fetch data again we have our own clean data here in our controller... also I would like to make it better by putting this part in the service inside a wrapper that looks if the local data is empty call fetchdata and follow the same steps else return the populated local data (local to the service) and many controller can now have access to the same data as it should be
        $scope.names.forEach(function(name){$scope.lengths.push(name.length);})
        console.log($scope.lengths);
        });
    
    
    }]);
    // I hope this helpes people new to the whole promises and asynch methods in general
    

    由于我仍在学习这种异步方法,因此如果我在任何地方出现理解错误,请告诉我,我将不胜感激。

    <!Doctype HTML>
    <html>
    <head>
        <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
        <!-- Angular JS library-->
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
        <script type="text/javascript" src="https://code.angularjs.org/1.4.3/angular-resource.min.js"></script>
        <script type="text/javascript" src="https://code.angularjs.org/1.4.3/angular-route.min.js"></script>
        <!-- Latest compiled and minified CSS -->
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
        <!-- Optional theme -->
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
        <!-- Latest compiled and minified JavaScript -->
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
        <!-- D3.js library -->
        <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
        <script type="text/javascript" src="app.js"></script>
    </head>
    
    <body ng-app="app" class="container">
        <div ng-controller="controller1">
            <div ng-repeat="n in names">
                {{n}}-------{{lengths[$index]}}
            </div>
        </div>
    </body>
    

    这是我用来查看范围的 index.html 它就像魔术一样......如果有人在我将它与 D3 结合使用时感兴趣,请告诉我,我会将它包含在此处。 以后的人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-28
      • 2017-03-17
      • 1970-01-01
      • 2012-10-20
      • 1970-01-01
      相关资源
      最近更新 更多