开发者

jQuery: how to make a global variable accessible within $.ajax() [duplicate]

This question already has answers here: Closed 11 years ago.

Possible Duplicate:

Can't access global variable in jQuery $.get within function

This is probably a newbie problem, but here it goes: I declared a global variable called preview. With AJAX, I get a json array and loop through it. For each iteration, I do another AJAX call to get a string and append it to the global variable.

However, printing the global variable after the second AJAX call gives me "empty string" (I am definitely getting a string back from the second AJAX call).

Here's the code:

var preview;
$("#some-button").click(function(e){
    e.preventDefault();
    var companies = "blahblahblah";

    $.ajax({
        url: "tracklink/getemails.php",
        type: "POST",
        data: "companies=" + companies,
        dataType: "json",
        success: function(databack) {
            if (databack) {
                for (i=0; i<databack.length; i=i+1) {
                    preview = "";
                    $("#selected-clip-list li").each(function(){
                        $.ajax({
                            url: "tracklink/cksum.php",
                            type: "POST",
                            data: "video_id=" + $(this).attr("clip_id") +开发者_如何学Go "&addr=" + databack[i].email_address,
                            success: function (msg) {
                                if (msg) {
                                    preview += msg;
                                }
                                //this works
                                //console.log(preview);
                            }
                        });
                    });
                    //doesn't work
                    console.log(preview);
                }
            }
        }
    });
});

Any idea why I'm getting "empty string"?

Many thanks.


Because Ajax is asynchronous. This line:

//doesn't work
console.log(preview);

is executed before the response is processed. That is the reason why you provide a callback function (success:) to process the response.

All the code that has to deal with the response has to be inside or called from the callback.

It is not related to preview not being accessible in the callback (because it is accessible).

Update: You could solve this using Deferred objects:

success: function(databack) {
        if (databack && databack.length > 0) {
            var deferred = $.Deferred();

            preview = "";
            for (i=0; i<databack.length; i=i+1) {
                $("#selected-clip-list li").each(function(){
                    deferred = deferred.pipe($.ajax({...}));
                });                  
            }
            deferred.then(function() {
                console.log(preview);
            });
        }
    }

This will execute the Ajax requests sequentially (but non-blocking) so that the responses are appended to preview in the correct order. But actually it is not 100% clear to me which data you want to collect in preview. Are you sure this nested for loop is correct?

If you don't care about the order of the Ajax requests, you can also do this:

var deferreds = [];
for (i=0; i<databack.length; i=i+1) {
    $("#selected-clip-list li").each(function(){
       deferreds.push($.ajax({...}));
    });                  
}
$.when.apply($, deferreds).then(function() {
    console.log(preview);
});


Unfortunately because the AJAX requests are asynchronous, that will not work as you expect it to. You are essentially setting preview to empty, dispatching a bunch of requests, and then printing out the empty variable. The requests will finish later and fill it up, but it will have already been printed.

Here is a basic reworked version of what you had, but done a bit better. Just remember that each of these functions returns before the ajax request has even completed, and then next one is called once all the requests are done. And this avoids even using an ugly global variable.

$("#some-button").click(function(e){
  e.preventDefault();

  $.ajax({
    url: "tracklink/getemails.php",
    type: "POST",
    data: "companies=" + companies,
    dataType: "json",
    success: emailSuccess
  });

  // When the email list is returned, 
  // Look up previews for each one.
  function emailSuccess(databack) {
    if (databack) {
      for (var i=0; i<databack.length; i=i+1) {
        queryPreviews(databack[i]);
      }
    }
  }

  // Sends off ajax requests for the items
  // and calls 'previewComplete' when the preview is ready.
  function queryPreviews(data) {
    var preview = "";
    var completed = 0;

    var items = $("#selected-clip-list li");

    items.each(function(i){
      $.ajax({
        url: "tracklink/cksum.php",
        type: "POST",
        data: "video_id=" + $(this).attr("clip_id") + "&addr=" + data.email_address,
        success: function (msg) {
          completed++;
          if (msg) {
              preview += msg;
          }

          // When all of the ajax requests are done
          // Call a function to do what needs to be done with preview
          if (completed == items.length) {
            previewComplete(preview);
          }
        }
      });
    });
  }

  // Do whatever you need to do with the preview
  function previewComplete(preview) {
    console.log(preview);
  }
});
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜