0

Possible Duplicate:
passing index from for loop to ajax callback function (javascript)

I'd like to delay the i++ until the jquery callback is done. i have this:

        for (var i = 0; i < stocks.length; i++) {
        var lastprice = 0
        var stock = stocks[i].stock;
        $.getJSON('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20("' + stock + '")&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys',
          function(data) {
            lastprice = data.query.results.quote.LastTradePriceOnly;
          }).done(function() {
             console.log(stock, lastprice);
            });
        };

and the problem is the loop finishes before the .getJSON does, and so I just end up console logging the last stock in my array, but the prices of all the stocks in my array. I tried this but it just kills my browser:

        for (var i = 0; i < stocks.length;) {
        var lastprice = 0
        var stock = stocks[i].stock;
        $.getJSON('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20("' + stock + '")&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys',
          function(data) {
            lastprice = data.query.results.quote.LastTradePriceOnly;
          }).done(function() {
             console.log(stock, lastprice);
             i++;
            });
        };

Anyone know what I'm doing wrong? Thanks!

Community
  • 1
  • 1
vincewilfork
  • 127
  • 1
  • 1
  • 6
  • Why would you be waiting until each JSON call was done to start the next iteration? – Tejs Nov 01 '12 at 15:16

3 Answers3

0

One of the following should do what you are looking for:

http://jsfiddle.net/BxKKP/

var stocks = [
      {"stock":"aapl"},
      {"stock":"yhoo"}
]

for (var i = 0; i < stocks.length;i++) {
    var stock = stocks[i].stock;

    $.ajax({
          url: 'http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20("' + stock + '")&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys',
          dataType: 'json',
          async: false,
          success: function(data) {
              console.log(stock, data.query.results.quote.LastTradePriceOnly);
          }
    });
};​

OR also: http://jsfiddle.net/9NrxY/

var stocks = [
      {"stock":"aapl"},
      {"stock":"yhoo"}
]

for (var i = 0; i < stocks.length;i++) {
    var stock = stocks[i].stock;

     $.getJSON('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20("' + stock + '")&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys',
      function(data) {
        console.log(data.query.results.quote.Symbol, data.query.results.quote.LastTradePriceOnly);
      });
};​
Tuanderful
  • 1,337
  • 1
  • 10
  • 13
0

The reason your for loop if killing your browser is because you accidentally employed something called busy waiting (bad). http://en.wikipedia.org/wiki/Busy_waiting

I don't know the context of your problem, but unless this is occurring during the initial load of the page, you should avoid synchronous execution. Instead, structure your code so that it's event-driven.

For example, if the for loop is for generating rows in a table, have the actual rendering of the row occur inside the success callback function of your ajax call.

Example:

for (var i = 0; i < stocks.length; i++) {
    var lastprice = 0
    var stock = stocks[i].stock;
    $.getJSON('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20("' + stock + '")&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys', function(data) {
        lastprice = data.query.results.quote.LastTradePriceOnly;
        //RENDER ROW
        $('<span class="row"/>').html(lastprice).appendTo('#TABLE_BODY_ELEMENT');
    })
};​

If you use synchronous instead of asynchronous, every time that loop hits the .getJSON() call it'll freeze, making your whole page freeze up.

adamb
  • 4,815
  • 1
  • 25
  • 40
-1

You're problem is that getJson in executing asynchronicly, buth you need synchronic execution. Try using $.ajax instead of $.getJson. In $.ajax set properties dataType to json and async to false.

OR based on comments try setting $.ajaxSetup({ async: false });

   for (var i = 0; i < stocks.length; i++) {
    var lastprice = 0
    var stock = stocks[i].stock;
    $.ajaxSetup({  async:false});
    $.getJSON('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20("' + stock + '")&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys',
      function(data) {
        lastprice = data.query.results.quote.LastTradePriceOnly;
      }).done(function() {
         console.log(stock, lastprice);
        });
    };
elrado
  • 4,960
  • 1
  • 17
  • 15
  • No way. Async calls are plain bad, there are many ways to get around this issue. – moonwave99 Nov 01 '12 at 15:32
  • @elrado Thanks for the help and synchronic execution makes sense but its still logging the last array in stocks, not each array. Would ajaxsetup need something else? – vincewilfork Nov 01 '12 at 15:33
  • there was type it is not asny:false buth async: false. And yes @moonwave99 there are other ways, but the easiest way is to to give me some negative reputation and do nothing to help vincewilfork. – elrado Nov 01 '12 at 15:37
  • @moonwave99 Async calls are bad? Quite the contrary. AJAX calls allow you to perform functionality that would otherwise be impossible. Just take a look at Google Maps. – adamb Nov 01 '12 at 15:37
  • Pardon, I meant ajax call performed the `sync` way. – moonwave99 Nov 01 '12 at 16:19