Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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!

share|improve this question
You use getHistoricalPrice() before its definition. – Darin Kolev Dec 20 '12 at 19:52
@DarinKolev Thanks for your suggestion. From where I call the function, I can successfully write the entire object out to console and I can see all of the correct data in the object's arrays and data in the console. However, I cannot access the elements directly via Javascript. – Curt Dec 20 '12 at 23:06

4 Answers

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.

share|improve this answer
Thanks BobS for your suggestion. From where I call the function, I can successfully write the entire object out to console and I can see all of the object's arrays and data in the console. Doesn't this mean that it was populated? However, I cannot access the elements of this object. Nevertheless, I will try your suggestion. – Curt Dec 20 '12 at 22:12
I tried putting in a callback function into my local files. The callback did not get executed. You can get an idea of what I did at my updated jsFiddle: jsfiddle.net/curt00/LTazR/7 I welcome any other suggestions. – Curt Dec 21 '12 at 0:32
I got the callback to work, but I have the exact same situation as before. When I write the object to console, all of the contents (array) are correct, but I cannot access the array with Javascript from where the function is called. – Curt Dec 21 '12 at 1:15

See my answer on http://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");
};
share|improve this answer

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.

share|improve this answer
up vote 0 down vote accepted

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;
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.