Calciphus
Calciphus

Reputation: 146

Is there a way to pass variables from beforeSend to success functions in the jQuery .ajax function?

The Problem

When working with AJAX to query a remote API, by the asynchronous nature of the request it comes back whenever it completes. The problem is when I have to make iterative calls to the same API with different criteria, I don't know which response is coming back.

The question: Is it possible to pass a variable from

Sample code: (simplified)

n=5;
for(i=0; i < n; i++) {
  $.ajax({
    url: someURL,
    method: post,
    // I don't want to have to use async: false, that's bad
    // async: false,
    data: JSON.stringify(someData),
    beforeSend: function(){
      console.log("Starting request #"+i)
    },
    error: function(err, code, text) {
      alert("Something went wrong: \n\n" + code + ": " + text);
    },
    success: function(response) {
      console.log("Response for request #"+i)
      console.log(response)
    }
  })
}

The problem comes up in that final success function: What I should see is:

Starting request #0
Starting request #1
Starting request #2
Starting request #3
Starting request #4
Response for request #2
[object]
Response for request #1
[object]
Response for request #4
[object]
Response for request #0
[object]
Response for request #3
[object]

What I actually see is:

Starting request #0
Starting request #1
Starting request #2
Starting request #3
Starting request #4
Response for request #4
[object]
Response for request #4
[object]
Response for request #4
[object]
Response for request #4
[object]
Response for request #4
[object]

This is important not because I care about my logs being right, but because the actual version needs to be able to reconcile the responses with what was sent. I don't want to go synchronous on this, because it'll be slow, annoying, and possibly time out.

Upvotes: 3

Views: 1632

Answers (2)

Michael Bates
Michael Bates

Reputation: 1934

Use a function to make the AJAX request, and pass i to that function:

var n = 5;
for(i = 0; i < n; i++) {
  makeRequest(i);
}

function makeRequest(i) {
  $.ajax({
    url: url,
    method: 'POST',
    data: JSON.stringify(someData),
    beforeSend: function(){
      console.log("Starting request #"+i)
    },
    error: function(err, code, text) {
      console.log("Response for request #"+i)
      ...
    },
    success: function(response) {
      console.log("Response for request #"+i)
      ...
    }
  });
}

Upvotes: 1

Don McCurdy
Don McCurdy

Reputation: 11970

As mentioned in the comments, this is a special case of a more common mistake with closures in loops. Since the value of i will have changed by the time success runs, you'll want to store it (by calling a helper function outside the loop which makes the ajax request) or bind i to the success function. Example:

for (var i = 0; i < 5; i++) {
    $.ajax({
        url: '/url',
        success: function (i, response) {
            console.log("Response for request #"+i);
            console.log(response);
        }.bind(window, i)
    });
}

Upvotes: 5

Related Questions