By Artem Tikhomirov


2008-09-25 13:26:54 8 Comments

I have a JavaScript widget which provides standard extension points. One of them is the beforecreate function. It should return false to prevent an item from being created.

I've added an Ajax call into this function using jQuery:

beforecreate: function (node, targetNode, type, to) {
  jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),

  function (result) {
    if (result.isOk == false) 
        alert(result.message);
  });
}

But I want to prevent my widget from creating the item, so I should return false in the mother-function, not in the callback. Is there a way to perform a synchronous AJAX request using jQuery or any other in-browser API?

14 comments

@Tell Me How 2019-05-13 06:14:59

This is my “Thread” namespace:

var Thread = {
    sleep: function(ms) {
        var start = Date.now();

        while (true) {
            var clock = (Date.now() - start);
            if (clock >= ms) break;
        }

    }
};

And this is how I call it:

var d1 = new Date();
console.log('start ' + d1.toLocaleTimeString());
Thread.sleep(10000);
var d2 = new Date();
console.log('end ' + d2.toLocaleTimeString());

And if looking at the console we get the following result:

start 1:41:21 PM
end 1:41:31 PM

@Endless 2016-12-13 12:55:38

Note: You shouldn't use async: false due to this warning messages:

Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), synchronous requests on the main thread have been deprecated due to the negative effects to the user experience.

Chrome even warns about this in the console:

Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.

This could break your page if you are doing something like this since it could stop working any day.

If you want to do it a way that still feels like if it's synchronous but still don't block then you should use async/await and probably also some ajax that is based on promises like the new Fetch API

async function foo() {
  var res = await fetch(url)
  console.log(res.ok)
  var json = await res.json()
  console.log(json)
}

Edit chrome is working on Disallowing sync XHR in page dismissal when the page is being navigated away or closed by the user. This involves beforeunload, unload, pagehide and visibilitychange.

if this is your use case then you might want to have a look at navigator.sendBeacon instead

It is also possible for the page to disable sync req with either http headers or iframe's allow attribute

@inostia 2017-04-19 21:39:15

Note that you should wrap your await fetch(url) call in a try... catch block to catch any asynchronous errors.

@Endless 2017-04-20 08:47:38

the function foo has been converted to a promise by just using the word async in the beginning, so you could just do foo().catch(...) to catch it also

@Alex 2019-06-20 10:45:05

Chrome already disallowed async ajax inside page beforeunload but then reverted the change back after negative feedback bugs.chromium.org/p/chromium/issues/detail?id=952452

@Geoffrey 2018-04-29 10:50:01

Because XMLHttpReponse synchronous operation is deprecated I came up with the following solution that wraps XMLHttpRequest. This allows ordered AJAX queries while still being asycnronous in nature, which is very useful for single use CSRF tokens.

It is also transparent so libraries such as jQuery will operate seamlessly.

/* wrap XMLHttpRequest for synchronous operation */
var XHRQueue = [];
var _XMLHttpRequest = XMLHttpRequest;
XMLHttpRequest = function()
{
  var xhr   = new _XMLHttpRequest();
  var _send = xhr.send;

  xhr.send = function()
  {
    /* queue the request, and if it's the first, process it */
    XHRQueue.push([this, arguments]);
    if (XHRQueue.length == 1)
      this.processQueue();
  };

  xhr.processQueue = function()
  {
    var call = XHRQueue[0];
    var xhr  = call[0];
    var args = call[1];

    /* you could also set a CSRF token header here */

    /* send the request */
    _send.apply(xhr, args);
  };

  xhr.addEventListener('load', function(e)
  {
    /* you could also retrieve a CSRF token header here */

    /* remove the completed request and if there is more, trigger the next */
    XHRQueue.shift();
    if (XHRQueue.length)
      this.processQueue();
  });

  return xhr;
};

@paulo62 2014-11-15 11:33:46

I used the answer given by Carcione and modified it to use JSON.

 function getUrlJsonSync(url){

    var jqxhr = $.ajax({
        type: "GET",
        url: url,
        dataType: 'json',
        cache: false,
        async: false
    });

    // 'async' has to be 'false' for this to work
    var response = {valid: jqxhr.statusText,  data: jqxhr.responseJSON};

    return response;
}    

function testGetUrlJsonSync()
{
    var reply = getUrlJsonSync("myurl");

    if (reply.valid == 'OK')
    {
        console.dir(reply.data);
    }
    else
    {
        alert('not valid');
    }    
}

I added the dataType of 'JSON' and changed the .responseText to responseJSON.

I also retrieved the status using the statusText property of the returned object. Note, that this is the status of the Ajax response, not whether the JSON is valid.

The back-end has to return the response in correct (well-formed) JSON, otherwise the returned object will be undefined.

There are two aspects to consider when answering the original question. One is telling Ajax to perform synchronously (by setting async: false) and the other is returning the response via the calling function's return statement, rather than into a callback function.

I also tried it with POST and it worked.

I changed the GET to POST and added data: postdata

function postUrlJsonSync(url, postdata){

    var jqxhr = $.ajax({
        type: "POST",
        url: url,
        data: postdata,
        dataType: 'json',
        cache: false,
        async: false
    });

    // 'async' has to be 'false' for this to work
    var response = {valid: jqxhr.statusText,  data: jqxhr.responseJSON};

    return response;
}

Note that the above code only works in the case where async is false. If you were to set async: true the returned object jqxhr would not be valid at the time the AJAX call returns, only later when the asynchronous call has finished, but that is much too late to set the response variable.

@James in Indy 2010-04-07 13:30:16

Excellent solution! I noticed when I tried to implement it that if I returned a value in the success clause, it came back as undefined. I had to store it in a variable and return that variable. This is the method I came up with:

function getWhatever() {
  // strUrl is whatever URL you need to call
  var strUrl = "", strReturn = "";

  jQuery.ajax({
    url: strUrl,
    success: function(html) {
      strReturn = html;
    },
    async:false
  });

  return strReturn;
}

@Lightness Races with Monica 2011-07-11 23:35:29

That's because you were returning a value out of the callback, not out of getWhatever. Thus you returned nothing i.e. undefined from your getWhatever.

@Thomas Fritz 2012-02-22 11:30:54

this is absolutely wrong. You can't be sure that an asynchronous call has finished when returning 'strReturn'.

@James in Indy 2012-03-05 18:13:06

This is a Synchronous call (async:false).

@Sydwell 2011-04-12 21:45:44

You can put the jQuery's Ajax setup in synchronous mode by calling

jQuery.ajaxSetup({async:false});

And then perform your Ajax calls using jQuery.get( ... );

Then just turning it on again once

jQuery.ajaxSetup({async:true});

I guess it works out the same thing as suggested by @Adam, but it might be helpful to someone that does want to reconfigure their jQuery.get() or jQuery.post() to the more elaborate jQuery.ajax() syntax.

@Juan Mendes 2014-08-04 18:16:30

This is a really bad idea, why would you set it at a global level? And then be forced to unset it after?

@Rzassar 2016-05-31 03:22:23

At least, this is the best bad idea. instead of saying: "THERE IS NO WAY EXCEPT $.ajax()". ;)

@Felipe Marques 2018-02-15 19:55:31

this is my simple implementation for ASYNC requests with jQuery. I hope this help anyone.

var queueUrlsForRemove = [
    'http://dev-myurl.com/image/1', 
    'http://dev-myurl.com/image/2',
    'http://dev-myurl.com/image/3',
];

var queueImagesDelete = function(){

    deleteImage( queueUrlsForRemove.splice(0,1), function(){
        if (queueUrlsForRemove.length > 0) {
            queueImagesDelete();
        }
    });

}

var deleteImage = function(url, callback) {
    $.ajax({
        url: url,
        method: 'DELETE'
    }).done(function(response){
        typeof(callback) == 'function' ? callback(response) : null;
    });
}

queueImagesDelete();

@Sheo Dayal Singh 2017-10-03 09:52:59

Firstly we should understand when we use $.ajax and when we use $.get/$.post

When we require low level control over the ajax request such as request header settings, caching settings, synchronous settings etc.then we should go for $.ajax.

$.get/$.post: When we do not require low level control over the ajax request.Only simple get/post the data to the server.It is shorthand of

$.ajax({
  url: url,
  data: data,
  success: success,
  dataType: dataType
});

and hence we can not use other features(sync,cache etc.) with $.get/$.post.

Hence for low level control(sync,cache,etc.) over ajax request,we should go for $.ajax

 $.ajax({
     type: 'GET',
      url: url,
      data: data,
      success: success,
      dataType: dataType,
      async:false
    });

@Serge Shultz 2015-05-10 06:28:53

Keep in mind that if you're doing a cross-domain Ajax call (by using JSONP) - you can't do it synchronously, the async flag will be ignored by jQuery.

$.ajax({
    url: "testserver.php",
    dataType: 'jsonp', // jsonp
    async: false //IGNORED!!
});

For JSONP-calls you could use:

  1. Ajax-call to your own domain - and do the cross-domain call server-side
  2. Change your code to work asynchronously
  3. Use a "function sequencer" library like Frame.js (this answer)
  4. Block the UI instead of blocking the execution (this answer) (my favourite way)

@Spen 2016-08-20 19:52:07

With async: false you get yourself a blocked browser. For a non blocking synchronous solution you can use the following:

ES6/ECMAScript2015

With ES6 you can use a generator & the co library:

beforecreate: function (node, targetNode, type, to) {
    co(function*(){  
        let result = yield jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
        //Just use the result here
    });
}

ES7

With ES7 you can just use asyc await:

beforecreate: function (node, targetNode, type, to) {
    (async function(){
        let result = await jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
        //Just use the result here
    })(); 
}

@Daniel Krom 2018-05-07 16:05:24

Notice you can just pass async function to beforecreate beforecreate: async function(.... and remove the self invoked async function

@BishopZ 2012-04-28 17:41:39

All of these answers miss the point that doing an Ajax call with async:false will cause the browser to hang until the Ajax request completes. Using a flow control library will solve this problem without hanging up the browser. Here is an example with Frame.js:

beforecreate: function(node,targetNode,type,to) {

    Frame(function(next)){

        jQuery.get('http://example.com/catalog/create/', next);
    });

    Frame(function(next, response)){

        alert(response);
        next();
    });

    Frame.init();
}

@Distortum 2014-05-19 02:08:45

Synchronous calls are handy if you want to put together a quick test harness for a REST back-end and would prefer simplicity over callback hell.

@Adam Bellaire 2008-09-25 13:30:37

From the jQuery documentation: you specify the asynchronous option to be false to get a synchronous Ajax request. Then your callback can set some data before your mother function proceeds.

Here's what your code would look like if changed as suggested:

beforecreate: function (node, targetNode, type, to) {
    jQuery.ajax({
        url: 'http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
        success: function (result) {
            if (result.isOk == false) alert(result.message);
        },
        async: false
    });
}

@SLA80 2010-05-16 11:41:21

Exactly, it is impossible to use get(), post(), load() for synchronous calls. Only ajax() have "async" parameter, which can be set to "false".

@StuperUser 2011-08-01 17:45:25

@SLA80 Nope. Since jQuery 1.1: stackoverflow.com/questions/6849686/…

@qualidafial 2012-03-08 17:58:24

@StuperUser: the answer is still correct, and relevant if you only want only certain requests to be synchronous.

@StuperUser 2012-03-08 18:00:16

@qualidafial my comment is aimed at SLA80's incorrect comment; it is possible to use get(), post(), load() for synchronous calls.

@d-_-b 2013-02-15 23:07:25

just a note, adding the async:false works great for me, as long as I set the entire ajax function as the value of some variable. for example, var ajaxresults = $.ajax({....

@ken 2015-08-05 08:43:03

async false is no longer supported for jQuery >= 1.8. Refer to api.jquery.com/jQuery.ajax

@Ben Johnson 2015-10-30 14:09:02

@ken async: false is still supported in jQuery >= 1.8. The ability to use async: false with jqXHR ($.Deferred) is what was deprecated. In other words, one must use the newer success/error/complete callback options, instead of the legacy methods, e.g., jqXHR.done().

@Swap-IOS-Android 2017-08-16 07:34:05

Is it safe to use Async:False, Because it will hold the execution of rest code. Once you get response of ajax, only then, rest of the code will execute. What is good way to handle if server does not response to Ajax request? should i add timeout to continue other request if server does not response to Ajax request?

@Ikbel 2017-09-14 17:47:53

async is deprecated

@thomasb 2017-11-16 13:10:12

@Ikbel : no, see Ben Johnson's comment. It's been deprecated in conjunction with $.Deferred, not by itself.

@bishal 2018-03-07 06:02:23

Important to note async: false option is deprecated for newer versions of jQuery > 3.0 . Thus, this method is not implementable.

@John Neuhaus 2018-06-29 19:16:52

@bis Not true. As of this comment, the official docs still don't list it as deprecated, and it works without generating a warning. See this fiddle

@abilash er 2018-06-30 06:34:50

please check this question also stackoverflow.com/questions/51112102/…

@searching9x 2014-08-16 13:20:10

This is example:

$.ajax({
  url: "test.html",
  async: false
}).done(function(data) {
   // Todo something..
}).fail(function(xhr)  {
   // Todo something..
});

@Gone Coding 2017-09-05 18:22:55

What is the point of using async false with a promise-based solution. This only locks up the browser for no benefit at all.

@Nikki 2017-10-06 12:05:31

@GoneCoding there are situations where want to execute code in exact sequence, in that situation we can use async false

@Gone Coding 2017-10-06 21:38:22

@Nikki: That is absolutely not the way to run them sequentially. Use async promises (which ajax calls already return) and .then() or done() (as it already shows). Locking up the browser is a very poor user experience. As I said having async: false in this example is a complete waste of time.

@Carcione 2012-04-25 15:34:38

function getURL(url){
    return $.ajax({
        type: "GET",
        url: url,
        cache: false,
        async: false
    }).responseText;
}


//example use
var msg=getURL("message.php");
alert(msg);

@Hari 2015-05-07 20:09:39

Note that though, you might get this: 'Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience.'

@Jose Nobile 2016-02-09 21:29:41

@Hari What is the way to perform a synchronous ajax call using jQuery without use the main thread?

@moopet 2016-10-26 10:13:04

I don't see that this answer has anything to offer, it's just the accepted answer wrapped into a function and answered four years later. It's a bad thing to advise people to C+P, because the function does not indicate what it does. "So getURL vs get ? why does one hang my browser?" etc.

Related Questions

Sponsored Content

33 Answered Questions

[SOLVED] How can I upload files asynchronously?

27 Answered Questions

[SOLVED] How can I refresh a page with jQuery?

31 Answered Questions

[SOLVED] How to manage a redirect request after a jQuery Ajax call

13 Answered Questions

[SOLVED] How can I select an element with multiple classes in jQuery?

73 Answered Questions

[SOLVED] How can I get query string values in JavaScript?

14 Answered Questions

[SOLVED] How can I select an element by name with jQuery?

19 Answered Questions

[SOLVED] How can I get the ID of an element using jQuery?

20 Answered Questions

[SOLVED] Wait until all jQuery Ajax requests are done?

17 Answered Questions

[SOLVED] Abort Ajax requests using jQuery

34 Answered Questions

Sponsored Content