0

I'm having difficult to understand the $.get call inside a loop . On the example below I call a $.get inside a function (The file that i'm reading on $.get doesn't matter for this problem), and it seems to be read just after all the first loop is finished.

I expect console to show:

---
1
---
2
---
3
---

But is showing

1
2
3
4
5
6
7
8
9
10
---(11)

Can you tell me why?

http://jsfiddle.net/qh6zn514/1/

<Button id="clickme">Click me</button>

$("#clickme").click(function() {
   for ($i=0;$i<=10;$i++)
   {
      readNumber();  
      console.log($i);
   }    
})

function readNumber () {   
    $.get ("file", function(txt) {
      console.log ("---");    
    });    
}
Alex Palombo
  • 135
  • 1
  • 2
  • 8
  • 1
    For a minute I thought that loop was PHP. – Sterling Archer Oct 31 '14 at 18:37
  • AJAX requests are queued and run asynchronously. You told it to queue and execute 10 AJAX requests, so it did, it just so happened that you queued them way faster than the requests could actually process. – qJake Oct 31 '14 at 18:37
  • 1
    Maybe a duplicate of [Make the loop wait for the ajax call](http://stackoverflow.com/q/23740051/710446). (Doing `return $.get(...)` and `readNumber().then(function() { console.log(...) })` seems like a workable solution, but [beware of variable scope when using async functions in loops](http://stackoverflow.com/q/750486/710446).) See also [How to return the response from an Ajax call?](http://stackoverflow.com/q/14220321/710446), though I'm not sure I'd call it a duplicate. – apsillers Oct 31 '14 at 18:42
  • Yes, I think is possible to call duplicate of make the loop wait for the ajax call, although would be very nice if someone answered here... – Alex Palombo Oct 31 '14 at 18:57
  • I already answered.. – Nicolas Oct 31 '14 at 20:12
  • Nicolas, your solution is a workaround to get the expected output, but doesn't fix my problem. I'll still be reading the file asynchronously. What if I want to break the for if I found a a condition on the file I'm reading? – Alex Palombo Nov 03 '14 at 10:05

2 Answers2

5

the function passed to $.get is executed async, meaning that it returns right away without waiting for get to complete. So the loop runs real quick and logs the numbers. Then each get request completes and logs the ---

Andrew Luo
  • 919
  • 1
  • 5
  • 6
  • Ok, thanks. Should I open another question to get a workaround for that or this topic can have a solution? – Alex Palombo Oct 31 '14 at 18:42
  • Check out my answer for a possible solution. – Nicolas Oct 31 '14 at 18:45
  • 1
    its easy, if you want each number to be separated by ---, just see the code Nicolas put, essentially moving the log($i) inside the function and allowing javascript closures to maintain the different values of $i. You should read more about closures in javascript. – Andrew Luo Oct 31 '14 at 18:49
1

Ajax requests are asynchronous as stated above. Read the above post for an explanation. Here is a possible solution for your code though:

http://jsfiddle.net/qh6zn514/1/

$("#clickme").click(function() {
   for ($i = 1; $i <= 10; $i++)
   {
       readNumber($i)
   }    
})

function readNumber ($i) {
    $.get ("file", function(txt) {
        console.log($i)
        console.log ("---");
    });
}

Output:

1
---
2
---
3
---
4
---
5
---
6
---
7
---
8
---
9
---
10
---
Nicolas
  • 1,125
  • 1
  • 15
  • 31