39

I am implementing a callback for a 3rdParty javascript library and I need to return the value, but I need to get the value from the server. I need to do something like this:

3rdPartyObject.getCustomValue = function {
   return $.getJSON('myUrl');
}

getJson uses XMLHttpRequest which (I believe) has both synchronous and asynchronous behaviors, can I use the synchronouse behavior?

reevesy
  • 3,452
  • 1
  • 26
  • 23
tpower
  • 56,100
  • 19
  • 68
  • 100
  • 3
    And why can't you use a callback for returning/getting the value? Also, try avoiding the synchronous behavior as much as possible, since it will lock up the browser UI during its processing. – PatrikAkerstrand Jun 01 '09 at 06:08
  • The calling code doesn't support call backs. – tpower Jun 01 '09 at 06:11

6 Answers6

103

Looking at the jQuery source code, this is all $.getJSON does:

getJSON: function( url, data, callback ) {
    return jQuery.get(url, data, callback, "json");
},

And this is all $.get does:

get: function( url, data, callback, type ) {
    // shift arguments if data argument was omitted
    if ( jQuery.isFunction( data ) ) {
        callback = data;
        data = null;
    }

    return jQuery.ajax({
        type: "GET",
        url: url,
        data: data,
        success: callback,
        dataType: type
    });
},

No black magic there. Since you need to customize stuff other than the basic $.getJSON functionality, you can just use the low-level $.ajax function and pass the async option as false:

$.ajax({
    type: 'GET',
    url: 'whatever',
    dataType: 'json',
    success: function() { },
    data: {},
    async: false
});
Cœur
  • 37,241
  • 25
  • 195
  • 267
Paolo Bergantino
  • 480,997
  • 81
  • 517
  • 436
  • when you pass `async: false` then how do you get the error message from `$.ajax`? – Zain Shaikh Nov 15 '11 at 07:36
  • 1
    Those convenience methods are almost like presets for the $.ajax function. They're only useful if you are using those exact ajax options. – styfle Oct 26 '12 at 18:22
15

You can also use the following before making your call:

$.ajaxSetup( { "async": false } );

I do not know the scope of the "async" property, I suspect that it is a global config. So consider whether you want to change this back to true after your synchronous call.

example:

3rdPartyObject.getCustomValue = function { 
    $.ajaxSetup( { "async": false } );
    var result = $.getJSON('myUrl');
    $.ajaxSetup( { "async": true } );
    return result;
}
reevesy
  • 3,452
  • 1
  • 26
  • 23
Jonathan
  • 151
  • 1
  • 2
7
var jsonObjectInstance = $.parseJSON(
    $.ajax(
        {
           url: "json_data_plz.cgi", 
           async: false, 
           dataType: 'json'
        }
    ).responseText
);
Charles
  • 538
  • 5
  • 9
ph1g
  • 81
  • 1
  • 1
3

But unless i am mistaken this code wouldn't work:

3rdPartyObject.getCustomValue = function {
  var json = $.ajax({
    type: 'GET',
    url: 'whatever',
    dataType: 'json',
    success: function() { },
    data: {},
    async: false
  });

return json;
}

As $.ajax returns the XHR object not the parsed json object.

You would need to do something more like:

var jsonLoader = function(url){
    this.url = url;
    this.rawData = {};
    this.getRawData();
};

jsonLoader.prototype.getRawData = function(){

    var json = $.ajax({
        type: 'GET',
        url: this.url,
        dataType: 'json',
        success: this.getRawData(this),
        data: {},
        async: false
    });
};

jsonLoader.prototype. getRawData = function(self){
    return function(json){self.rawData = json;};
};

var loadMe = new jsonLoader("Data.json");
loadMe.rawData //has the parsed json object

In fact there is probably a much neater way of achieving the same

2

If anybody ever has to do this in rails, I have a pretty clean way like this:

Setup your controller like this:

def my_ajax_action

    respond_to do |format|
      # if you use render, you won't need a view page, the ":json =>" part takes care of all 
      # the formatting
      format.json { render :json => @variable_containing_json }
    end

end

Setup the call in Javascript

function doAjaxWork( ) {

    var ret;

    $.ajax({
        type: 'GET',
        url: '/controller/action/param',
        dataType: 'json',
        complete: function(response) {
           ret = eval('(' + response.responseText + ')');
        },
        async: false
    });


    return ret;
}

Of course, don't do this sync stuff unless you have to. Oh and while I am showing javascript with urls in it, check out JSRoutes... it's makes these really clean.

Steve Sheldon
  • 6,421
  • 3
  • 31
  • 35
0

The scope of the async property is global, your method will synchronize the call.

slider
  • 11