2

I have the following piece of code, to get data from IMDB :

for(var i in titles)
{
 $.ajax({
 url: "http://www.imdbapi.com/?t=" + titles[i],
 dataType: 'jsonp',
 success: function(data) {
 $('body').append('"'+titles[i]+'",');
 $.each(data, function(key, val) {
 $('body').append('"'+val+'",');
 });
 $('body').append('<br>');
 window.setTimeout(null, 1000);
 }
 });
}

The code works ok, except for $('body').append('"'+titles[i]+'",'); which alway returns the same title.

kapa
78.9k21 gold badges167 silver badges179 bronze badges
asked Jun 8, 2011 at 10:16
2
  • titles[i] always returns the same title Commented Jun 8, 2011 at 10:20
  • Repeating yourself is clearly not helpful. Commented Jun 8, 2011 at 10:24

4 Answers 4

2

The loop executes completely before any of the success handlers are called, so when you get into a success handler "i" will be the last title.

You need something like

function makeSuccessHandler(titles, i) {
 return function (data) {
 $('body').append('"'+titles[i]+'",');
 $.each(data, function(key, val) {
 $('body').append('"'+val+'",');
 });
 $('body').append('<br>');
 window.setTimeout(null, 1000);
 }
}
for(var i = 0; i < titles.length; i++)
{
 $.ajax({
 url: "http://www.imdbapi.com/?t=" + titles[i],
 dataType: 'jsonp',
 success: makeSuccessHandler(titles, i)
 });
}
answered Jun 8, 2011 at 10:21
Sign up to request clarification or add additional context in comments.

Comments

1

You can not do it like that, the ajax call will execute asynchronous. When your success method is executed the value of your index variable will not be correct. You can fix it if you increment i from your sucess method, and ofcoruse not do a for loop

answered Jun 8, 2011 at 10:22

Comments

1

The success function is asynchronous (it needs to wait for imdb to respond), so it will always run after the entire loop has finished - so i, within that function, will always be the last i.

Easiest way to work around this is to utilise jQuery's each function:

$.each(titles, function (i, value) {
 $.ajax({
 success: function (data) {
 // as usual...
 }
 });
});

This works because a function preserves its own scope (and hence its own copy of i).

answered Jun 8, 2011 at 10:18

1 Comment

+1 - I think this is more elegant than having a handler function outside of the block.
0

The problem is that if you call an asynchronous function in a loop, it will use the last assigned value of enclosing variables.

This can be solved using currying

function appendTitle(var title)
{
 return function(var data) {
 $('body').append('"'+title+'",');
 $.each(data, function(key, val) {
 $('body').append('"'+val+'",');
 });
 $('body').append('<br>');
 window.setTimeout(null, 1000);
 }
}
for(var i in titles)
{
 $.ajax({
 url: "http://www.imdbapi.com/?t=" + titles[i],
 dataType: 'jsonp',
 success: appendTitle(titles[i])
 });
}
answered Jun 8, 2011 at 10:26

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.