0

having a little trouble with my variable scope in jQuery, how come if I do the console.log outside the .each loop I get an empty array on $stockData ? (if i do it inside the .each, it works just fine, logs the array each time a value is added)

$(document).ready(function(){
    // stock data will contain all the merged data from the database and yahoo queries
    var $stockData = new Array();

    // get data from yahoo and merge with dbData, add to stockData array
    $.getJSON( "/get_portfolio.php", function(dbData) {
        $.each( dbData, function(index) {
            var stock = dbData[index]
            $.ajax({
                url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%3D%22"+stock.stock_symbol+"%22&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys",
                crossDomain: true
            }).success(function(data){
                var quote = data.query.results.quote;
                $.extend(quote, stock);
                $stockData.push(quote);
            }); // end success
        });// end each
    }); // end getJSON
    console.log($stockData);
}); // end document.ready
  • 1
    fun fact: jQuery each loop can be written as `$.each( dbData, function(index, stock) {` it returns both the index and the value at index be default – stackoverfloweth Nov 16 '15 at 13:43
  • I really wish jQuery would deprecate the callback parameters to `$.ajax` and just do Promises instead... – Alnitak Nov 16 '15 at 13:47
  • Oh the question asked 100 times a day. You can not reference variables that are set in an asynchronous callback. Ajax 101 It is like ordering pizza online. You are trying to eat the pizza as soon as you push the order button. Problem is the pizzas have not been delivered yet, they are still being made. You need to wait for the pizzas to be delivered before you can eat them. – epascarello Nov 16 '15 at 13:55

2 Answers2

2

when you call

$.getJSON( "/get_portfolio.php", function(dbData) { ... });

this part:

function(dbData) { ... }

doesn't run right away. JavaScript says: "oh you did a http request? I'll hold onto this function you gave me and run it after the request is done". And the rest of your code will keep on running, so this:

console.log($stockData);

will run first. So the actual order of execution here is:

  1. you run getJSON
  2. console.log runs
  3. the HTTP request finishes and your callback runs

put the console.log inside the getJSON block, right after your .each loop:

$(document).ready(function(){
    // stock data will contain all the merged data from the database and yahoo queries
    var $stockData = new Array();

    // get data from yahoo and merge with dbData, add to stockData array
    $.getJSON( "/get_portfolio.php", function(dbData) {
        var requestsDone = 0;
        $.each( dbData, function(index) {
            var stock = dbData[index]
            $.ajax({
                url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%3D%22"+stock.stock_symbol+"%22&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys",
                crossDomain: true
            }).success(function(data){
                var quote = data.query.results.quote;
                $.extend(quote, stock);
                $stockData.push(quote);
                if(++requestsDone == dbData.length) done();
            }).error(function(){
                if(++requestsDone == dbData.length) done();
            });
        });// end each
        function done() {
            console.log($stockData); // put this here
        }
    }); // end getJSON

}); // end document.ready
David Zorychta
  • 13,039
  • 6
  • 45
  • 81
0

You need to wait getJSON function be completed, try this:

$(document).ready(function(){
    // stock data will contain all the merged data from our database and yahoo queries
    var $stockData = new Array();

    // get data from yahoo and merge with dbData, add to stockData array
    $.getJSON( "/get_portfolio.php", function(dbData) {
        $.each( dbData, function(index) {
            var stock = dbData[index]
            $.ajax({
                url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%3D%22"+stock.stock_symbol+"%22&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys",
                crossDomain: true
            }).success(function(data){
                var quote = data.query.results.quote;
                $.extend(quote, stock);
                $stockData.push(quote);
            }); // end success
        });// end each

        console.log($stockData);

    }); // end getJSON
});