Curt
Curt

Reputation: 1181

Cannot access elements in object returned by Javascript Function in AngularJS

Thanks to @asgoth, I am able to use AngularJS $http service to retrieve stock prices from Yahoo as described here: Cannot read response from AngularJS $resource JSONP get from Yahoo Finance

In the "getHistoricalPrice" function, it puts the price inside an array, which is inside an object. From inside that function, I am able to access the price and write it to console.

The function returns the object to where it is called from. From there, I can successfully write the entire object out to console. However, I cannot access the elements of this object. I tried many different ways, but still cannot access the data in the object. You can see the code at http://jsfiddle.net/curt00/LTazR/2/ or below:

angular.module('app', ['ngResource']);

function AppCtrl($scope, $http, $resource) {

var historical_price = getHistoricalPrice("AAPL", 'start date is hard coded', 'end date is hard coded');
console.log("after calling historical price: ", historical_price);  // historical_price is an object and all of the correct data is outputted to console here, but I cannot access its elements directly from Javascript.

for(var key in historical_price) {
    console.log("key =",key);  // this outputs "key = list"
}

console.log("after calling getHistoricalPrice: ", historical_price.list[0][1]);  // Cannot access this as browser console gives error: TypeError: Cannot read property '1' of undefined
console.log("after calling getHistoricalPrice: ", historical_price['list'][0][1]);  // Cannot access this as browser console gives error: TypeError: Cannot read property '1' of undefined
console.log("after calling getHistoricalPrice: ", historical_price[0][1]);  // Cannot access this as browser console gives error: TypeError: Cannot read property '1' of undefined


function getHistoricalPrice(symbol, start, end) {

    var query = 'select * from csv where url=\'http://ichart.yahoo.com/table.csv?s=' + symbol + '&a=' + '11' + '&b=' + '19' + '&c=' + '2012' + '&d=' + '11' + '&e=' + '19' + '&f=' + '2012' + '&g=d&ignore=.csv\'';


    var url = 'http://query.yahooapis.com/v1/public/yql?q=' + fixedEncodeURIComponent(query) + '&format=json&callback=JSON_CALLBACK';

    var histData = {};

    $http.jsonp(url, {timeout: 30000}).success(function(json) {
        var list = [];


        var result = json.query.results.row;

        result.shift(); // remove the header (columns) row
        angular.forEach(result, function(row) {
            list.push([(new Date(row.col0)).getTime()/1000, parseFloat(row.col4)]);

        });
        list.sort(function(val1, val2) {
            return val1[0] - val2[0];
        });
        histData.list = list;
        console.log('Loaded historical data',histData.list[0][1],', for ' + symbol);  // This works and gives the price
    });

    return histData;
}

var fixedEncodeURIComponent = function(str) {
    return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
};



}


Any help or suggestions to solve this problem is greatly appreciate!

Upvotes: 2

Views: 1967

Answers (4)

Curt
Curt

Reputation: 1181

Thanks to everybody for providing suggestions.

I solved the problem by using AngularJS' $scope variable, such as $scope.symbol[user].price. I created this variable before calling the getHistoricalPrice function and then in that function, after the result is returned from $http.jsonp, I put the value into the $scope variable, as such:

$scope.symbol[user].price = row.col4;

Upvotes: 0

Mathew Berg
Mathew Berg

Reputation: 28750

BobS is right, you aren't timing things correctly. Also you declared fixedEncodeURIComponent after you had called it. This was resulting in an immediate error when I loaded up the jsfiddle.

While you were passing the callback through to your function correctly, you weren't actually calling it. I stripped out all the post processing of the json as you have some other errors involving the query and just implemented the callback so you can see it working.

After the request is finished and you're still in the success function you need to add

if(typeof(callback) === "function"){
    callback();
}

This calls that function you passed in and runs it. Here is a working jsFiddle of it: http://jsfiddle.net/LTazR/22/

I also updated a new variable i created call output so you can see it changing.

Upvotes: 1

asgoth
asgoth

Reputation: 35829

See my answer on https://stackoverflow.com/a/13967709/1916258

A great way to debug the Yahoo api is using the YQL Console: http://developer.yahoo.com/yql/console/

Info about the different posibilities (which stock info) can be found on http://www.gummy-stuff.org/Yahoo-data.htm

Edit: there was still a problem with function fixedEncodeURIComponent. It should encode quotes (") too:

var fixedEncodeURIComponent = function(str) {
    return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A").replace(/\"/g, "%22");
};

Upvotes: 1

BobS
BobS

Reputation: 2648

It's a matter of timing.

In lines 12-14 you are trying to access histData.list before it has been populated. This is because this code is run before the success callback to the $http.jsonp function is executed.

Any code that depends on that callback being completed must be in the callback or in a function called in the callback.

Upvotes: 1

Related Questions