3

I've just started working with JavaScript for non-trivial things, so this is probably straightforward...

What I'm trying to accomplish: iterate on an array of product references, fetch the JSON for each reference, and return an array of all the product information (with a hash-like structure indexed by reference).

What I've tried:

function fetchProductData(references){
  var product_data = new Object();
  references.forEach(function(ref){
    $.ajax({
      url: "http://localhost:3000/products/find.js?reference=" + ref,
      dataType: "jsonp",
      type: "GET",
      processData: false,
      contentType: "application/json",
      success: function(data) {
        product_data[ref] = data;
      }
    });
  });
  alert('before return: ' + product_data);
  return product_data;
};

$(document).ready(function(){
  var products = fetchProductData(references);
  alert('products : ' + products);
});

Here's what I don't understand: the first time I call alert to display the array contents, the array is empty. However, on the second call, the array is populated with the data I want.

In other words, the "products :" alert displays the data I want in the code above. But if I comment the "before return: " alert, it no longer does. Why is this?

So my question is: how can I have jQuery make several $.ajax call to fetch product information, collect that information in an array, and return that array so I can use it elsewhere in my code?

Also, why is the data in the variable magically accessible after it is referenced in an alert?

1
  • 1
    forEach is ES5. It does not work in IE8 Commented Apr 15, 2011 at 16:01

5 Answers 5

5

The "A" in "AJAX" stands for "asynchronous" :). Your program doesn't wait for the call to complete before going on to the next iteration, meaning you'll probably not get all of your data. Also the alert has the same problem. Operation to concat 'before return:' to the string add just enough time to get some data in the variable. On a faster machine you might find you never get data.

I think you really need to rethink your approach. It's not a good idea to have multiple AJAX requests in a loop. It will greatly increase latency of the page. Pass all your parameters once using JSON, then have your server side script loop through that and return a single response in JSON.

function fetchProductData(references){
  // make sure your "references" is a JSON object
  $.getJSON('http://server/side/url', {'json':references}, function(product_data) {
      // do something with product_data (alert them, put them in an array, etc)

  });
}
Sign up to request clarification or add additional context in comments.

1 Comment

Yes, I really should pass all references at once. I don't know why it didn't occur to me... Thanks!
4
function fetchProductData(references, cb){
  var length = 0;
  var product_data = new Object();
  references.forEach(function(ref){
    length++;
    $.ajax({
      url: "http://localhost:3000/products/find.js?reference=" + ref,
      dataType: "jsonp",
      type: "GET",
      processData: false,
      contentType: "application/json",
      success: function(data) {
        product_data[ref] = data;
        if (++count === length) {
          cb(product_data);
        }
      }
    });
  });

};

$(document).ready(function(){
  var products = fetchProductData(references, function(products) {
    alert('products : ' + products);
  });
});

Use a callback on your asynchronous operation.

The reason it appears to work with the alert call is because alerting a message gives ajax enough time to populate your array. The return statement is only triggered after you click OK on the alert box giving your code a window of 250ms to populate the array with data.

1 Comment

Thanks for explaining the array population latency. It's now clear to me why and how that worked.
1

You are executing you ajax query in async mode. And you want a sync result. Try to add:

async: false

Hope this helps.

Comments

0

your $.ajax call is asynchronous, so what is happening is that the first time you make the call, your javascript makes the call, moves on to the next line (alert) and then loops. You're data hasn't returned at that point yet. What you can do to remedy this is to set the async: false option in your $.ajax call.

3 Comments

synchronous ajax over a list is going to block and be really slow. You basically have to wait latency * references.length. So thats 20s for a list of 200 items.
@Raynos, completely agree it's not a great way to handle this. Ideally some bulk way to request the data would be preferred, or partial bulk loading letting that be processed for the user and let the rest be processed in the background
Ideally you never use synchronous XMLHTTPRequests :). Simply ask the server for data, giving some parameters. and handle the data when the server is done.
0

This is an asynchronous operation. The only sure way to know when the data is ready is in the callback function: success: function () {...}, which gets called when the data has finally returned. Put your alert in there.

Comments

Your Answer

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.