1
function jQueryFunction(url,callback)
{ 
    $.ajax
    ({
        type: "GET",
        async: false,
        url: url,
        dataType: "jsonp",
        jsonp: "callback",
        jsonpCallback: "tpsHandler",
        success: function(json)
        {
            return callback(json);
        }
    });  
}

function tmpFunction(callback) 
{
    var jsonArray = new Array();
    var i = 0;

    while(true)
    {
        for(var j = 0; j < url_array.length; j++)
        {
            jQueryFunction(url_array[j], function(json){
                jsonArray[j] = json;
                i++;
            });
        }

        if(i >= url_array.length)
        {
            return callback(jsonArray);
        }
        else
        {
            alert(i);
        }
    }
}

When I call tmpFunction the website keeps displaying "0" to me. Why is i always 0? Does tmpFunction never run the for loop?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
user2597504
  • 1,503
  • 3
  • 23
  • 32

3 Answers3

1

From the jQuery documentation:

By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active. As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated; you must use the success/error/complete callback options instead of the corresponding methods of the jqXHR object such as jqXHR.done() or the deprecated jqXHR.success().

As shown above, you can't use jsonp with synchronous requests. So yes, your success callback is not getting executed (not even sure whether jQuery would trigger a callback if a function is synchronous in lieu of just return the value).

Furthermore, I suggest that you never make synchronous AJAX requests since network requests are long-running operations that can destroy user experience. Instead, take @Altinak 's advice and use Deferred objects.

Travis Kaufman
  • 2,867
  • 22
  • 23
  • 1
    And on a higher (yet slightly less related) level, be very careful of how you use this function. Whomever maintains the API servers that your constant network requests are thrashing is probably not going to be a happy camper :) – Travis Kaufman Oct 03 '13 at 23:27
  • I believe you meant "never make _synchronous_ AJAX requests" – Alnitak Oct 04 '13 at 07:26
0

Place the i after the jQueryFunction call.

Don't forget to place a "break;" after alert(i) to get out of the while loop.

If the i must be inside the callback in jQueryFunction call use a done to place your code to execute after ajax, and don't use i. Change async to true in the ajax call to get done to work.

$.ajax( //your settings
).done(function(data){
    //check the value in data instead of i.
    //due to .ajax being asynchronous code that needs to wait needs
    //to be in .done or the success callback.
});
Quentin Engles
  • 2,744
  • 1
  • 20
  • 33
0

A better solution to this entire problem is to use deferred objects.

I'm going to ignore the while (true) bit for now, since that doesn't make sense:

function jQueryFunction(url)
{ 
    return $.ajax({
        type: "GET",
        async: true,                  // NB: **not** false
        url: url,
        dataType: "jsonp",
        jsonp: "callback",
        jsonpCallback: "tpsHandler"   // any good reason why you're defining this?
    });  
}

function tmpFunction(callback) 
{
    var def = [];     

    for (var i = 0; i < url_array.length; ++i) {
        def.push(jQueryFunction(url_array[i]));
    }

    return $.when.apply($, def).done(callback);
}

This will run all of the AJAX queries in parallel (subject to per-host client connection limits) and once they're all done, callback will be invoked with each of the results (in submission order) in the arguments array.

NB: this isn't quite the same as your original semantics which has callback passed a single parameter that is the array of results. If you want to keep that, use:

.done(function() {
    var args = [].slice.call(arguments, 0);
    callback.call(this, args);
});
Alnitak
  • 334,560
  • 70
  • 407
  • 495