1

I know scope should be simple. I can see that when going through the documentation on scoping, and when reading responses to the other people who've asked this here. That's why I'm confused. Here's the relevant chunk of code I'm working with:

$.ajax({
            type: "GET",
            url: locationURL,
            success: function (result) {
                console.log(result);
                var output = "<table><thead><tr><th>ID</th><th>Subject</th></thead><tbody>";
                for (var i in result.messages) {
                    var id = result.messages[i].id;
                    var locationURL = "https://www.googleapis.com/gmail/v1/users/me/messages/" + id + "?access_token=" + token;
                    var subject = "test";
                    $.ajax({
                        type: "GET",
                        url: locationURL,
                        success: function (result) {
                            subject = result.payload.headers[0].name;
                            console.log(subject);
                        }
                    });
                    console.log(subject);
                    output += "<tr><td>" + id + "</td><td>" + subject + "</td></tr>";
                }
                output += "</tbody></table>";

                display.html(output);
                $("table").addClass("table");
            }
        });

As you can probably tell, I am working with the Gmail API. So what am I doing here? The first ajax call is getting the list of all message ids. Then, for each message id I need to request message details, hence the nested ajax calls.

Now, the confusing part is this: In the outer ajax call's success function I define var subject = "test". I intend to overwrite this with the subject line from each message. Before I specifically look for the subject line in the payload of the message details, I just want to get some new string instead of test. In the success function on the nested ajax call I set subject = result.payload.headers[0].name; and the subsequent 'console.log(subject)' shows me that var subject has a new value. However, back in the outer ajax, when I add the next id and subject to my table, the value of subject still tests.

I would appreciate any pointers, thanks!

Gufran Hasan
  • 8,910
  • 7
  • 38
  • 51
el dubs
  • 13
  • 2
  • Possible duplicate of [jQuery AJAX calls in for loop](https://stackoverflow.com/questions/21819905/jquery-ajax-calls-in-for-loop) – abagh0703 Mar 07 '18 at 06:50
  • Your problem can be solved by realizing that `$.ajax` is asynchronous. the success function is only called when its done, but in meanwhile, your for loop has continued to create other ajax calls. – KarelG Mar 07 '18 at 06:50

1 Answers1

0

"Ajax" stands for "Asynchronous JavaScript and XML", meaning it's asynchronous. So whenever you call $.ajax, that code runs at the same time as the code right after that ajax call. This can be very useful, but also quite annoying in situations like yours where there's stuff outside the ajax call that depends on the data from the Ajax call. Typically this is what the success function is used for.

If you want a quick and dirty fix, you could add async:false as a key:value pair in your ajax call, although this is heavily frowned upon because it ruins the asynchronous power of ajax.

See this answer for information on how to make asynchronous ajax calls inside for loops work.

abagh0703
  • 841
  • 1
  • 12
  • 26