4
votes

From jQuery documentation:

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().

So what I understood from it is:

//deprecated usage 
$.ajax({
    url: "test.html",
    async:false,
    context: document.body
}).done(function() {
    //code to be executed after response received .
});

//valid usage 
$.ajax({
    url: "file.php",
    type: "POST",
    async: false,
    success: function(data) {
        //means http request status successful
        //code to be executed after response received .
        // my code 
    }
});

From jQuery docs:

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. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.

My question is:

  1. As I understand, in both cases code will be executed only after response is received. Both will lock the the browser as async:false. Then why one is valid and one is not? I am trying to understand what make the valid usage better or am I understanding this all wrong?

  2. I know synchronous request are not good (as they block UI) and are frowned upon. But sometimes client requirement forces your hand. For a registration form, I had implemented, I was asked to use google reCAPTCHA. Now the client wanted to inform the user if they had typed the wrong captcha before submitting. I implemented this by using synchronous ajax inside the onsubmit JavaScript function. How could this be done asynchronously? Can this be implemented differently without some kind of blocking? I am looking for alternate ideas of how this could be accomplished not code for this question.

While googling, I did find other SO question (links) on this, but could not find an answer which specified the difference between the valid and deprecated usage.

3

3 Answers

3
votes

Edit

It appears that lines 619 - 622 of the jQuery AJAX source code give you the answer as to how this works:

completeDeferred.add( s.complete );
jqXHR.done( s.success );
jqXHR.fail( s.error );

So internally, $.ajax is calling jqXHR.done and passes the state success function as the callback, which comes from here:

{
  success: yourSuccessFunction
}

On line 776, we can see that we return a jqXHR object, which could explain why (as of now) we're able to chain the .done() method:

return jqXHR;

Original answer

As I understand , in both cases code will be executed only after response is received. Both will lock the the browser as async:false. Then why one is valid and one is not. I am trying to understand what make the valid usage better or am I understanding this all wrong ?

Both are "valid", but .done is simply deprecated. The .done method follows the promise pattern, and is deprecated in favor of simply using the success callback. It's two different modes of execution, but both will have the same results. This is simply a move towards using a different API.

For example, here's the promise pattern (using the $q library):

var deferred = $q.deferred();

// something async, then
deferred.resolve(data);

return deferred.promise;

Whereas the success callback is simply... a callback:

function someFunction(cb) {
  // do something, then...

  return cb(data);
}

If .done is deprecated, this likely means that in future version of jQuery, the $.ajax method will no longer return a promise object, and thus you cannot call the .done method.

I know synchronous request are not good(as they block UI) and are frowned upon. But sometimes client requirement forces your hand. For a registration form , I had implemented, I was asked to use google recaptcha. Now the client wanted to inform the user if they had typed the wrong captcha before submitting. I implemented this by using synchronous ajax inside the onsubmit JavaScript function. How could this be done asynchronously ? Can this be implemented differently without some kind of blocking. I am looking for alternate ideas of how this could be accomplished not code for this question.

I would need to see more code, but if the captcha stuff happens asynchronously, then you'll need to call that first, wait for the response, and then execute the form submit:

checkCaptcha().then(function(result) {
  if(result === true) { // captcha passed the test
    // do your form submit
  } else {
    // possibly alert the user that the captcha didn't pass the test
  }
});
1
votes

I think you should avoid synchronous ajax in general, async: false with .done is deprecated, but async: true (default) with .done isn't, the result is the same but the browser isn't locked.

async: false with .done (as shown in @JoshBeam's answer) internally use the promise (.done) so you would end up using it twice.

This should be valid, using $.when() to synchronize code execution:

var promise = $.ajax({
    url: "test.html",
    /* async:true, // default */
    context: document.body
});
$.when(promise).done(function() {
  // code to be executed after response received
});
/* $.when() can wait for multiple promises */
0
votes

From what I gather $.ajax with async:false will in future versions not pass back a deferred object which is why .done() would not work since it expects a deferred object.

You do not need a synchronous ajax call for the situation you are describing. What you would do is prevent the form submission in the submit handler and then in the asynchronous ajax calls success handler you would check if the captcha is correct and submit the form from there. That way you can put in custom loading animations and things like that