-1

My browser (or the JQuery framework, to be more specific) prints the following warning to the browser's console:

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

I understand the warning, but not why it appears. To my understanding the call of asyncFunct() is asynchronous and therefore shouldn't print the warning message.

I'm using this JavaScript code:

var i18nObject;

$(document).ready(function () {
    // execute asyncFunct() asynchronously
    setTimeout(asyncFunct, 3000);
});

function asyncFunct() {
    alert(i18n("rejoin.title"));
}

function i18n(key) {
    if (typeof i18nObject == 'undefined') {
        // i18n not loaded yet, need to load it first
        $.ajax({
            url: 'UrlTo/i18n.json',
            async: false,
            dataType: 'json',
            success: function (response) {
                i18nObject = response;
            }
        });
    }
    if (i18nObject.hasOwnProperty(key)) {
        // key found
        return i18nObject[key];
    } else {
        // key not found
        return key;
    }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>

To face some concerns (from the comments) about async: false: This was deliberately chosen, as I need the function to return a value. I understand that using synchronous calls is a bad idea if they lock the UI. But why does this apply to my problem here? I want the call to asyncFunct() to be asynchronous.

Why am I receiving this warning, and is it possible to disable it? (to prevent unnecessary text in the console)

Nijin22
  • 850
  • 13
  • 20
  • 3
    It is clearly telling you not to use `async: false,` which is a terrible practice in the first place. Handle your response in the success callback. See [how-to-return-the-response-from-an-asynchronous-call](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – charlietfl Sep 07 '15 at 19:24
  • That warning suggests that if you want to use `async: false`, you should do it off the main thread. Take a look at using [Web workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers). – Amit Sep 07 '15 at 19:26
  • I've fixed this problem now by moving the i18n() call inside the done-function of another AJAX call. This works great for my specific problem (as I need to make the call anyways), but I'm still interested why this message was shown in the first place. – Nijin22 Sep 07 '15 at 19:30
  • @charlietfl Thanks for the link. In my case the i18n() function should only do the AJAX call if the i18nObject was not loaded previously. Is there a way to return it without making unnecessary AJAX calls (or returning a "call me again later, I'm still fetching value")? – Nijin22 Sep 07 '15 at 19:33
  • google the error for a full explanation – charlietfl Sep 07 '15 at 19:33
  • @charlietfl Sorry, If I've been unclear. I understand the error and the solution to the problem the error refers to. But I do NOT understand why the error applies to me. (This was the original question). By making the i18n() do a asynchronous call, it is no longer able to return a value. Therefore I can't use this solution. (Please correct me, if I'm wrong somewhere! - I don't have a lot of experience with JS and greatly appreciate any help) – Nijin22 Sep 07 '15 at 19:59
  • you made it `synchronous` is why by setting `async: false` You can pass a callback into your function and make it work fine asynchronously ... or return a promise from your function – charlietfl Sep 07 '15 at 20:03
  • @charlietfl Using a callback function seems like a good solution. Thanks. However, I think I think I still didn't fully understand why the call is synchronous. I de-synchronized asyncFunct() from the main thread by using setTimeout(). Shouldn't this mean that all functions called by asyncFunct() (i.e. i18n()) are also de-synchronized? – Nijin22 Sep 07 '15 at 20:23
  • You are mixing up 2 different concepts. The warning is about using `XMLHttpRequest` ($.ajax) in synchronous mode. It has nothing to do with using setTimeout – charlietfl Sep 07 '15 at 20:25

1 Answers1

1

Edit

Actually, since you are putting the sync call inside of a timeout, it appears that the call does happen asynchronously, as you correctly pointed out (see this jsbin for an example):

setTimeout(function() {
  $.ajax({
    method: 'GET',
    url: 'http://api.openweathermap.org/data/2.5/weather?q=London,uk',
    success: function(res) {
      console.log(res);
    },
    async: false
  });
}, 1000);

console.log('something synchronous');

If you open up the console, you'll notice that (as expected), something synchronous is logged first, and then a little over a second later, the result from our API is logged.

So I feel like there are two parts to this question that need to be addressed.

The first part is, why are you forcing a sync call to happen async, using a deprecated API, when you could just avoid the timeout altogether and simply make your XMLHttpRequest naturally asynchronous?

The second part is about suppressing the warning. It appears that the warning happens mistakenly, but the warning isn't looking at the fact that you made the sync request inside of a timeout. It's simply looking at the fact that you are using a deprecated API. In other words, the warning only cares about the usage of the deprecated API itself, and not the specific implementation.

However, if you really want to suppress these warnings, it'll be an all or nothing deal (see this answer for an example):

// define this as an empty function in your own code
console.log = function() {};

Original answer

To my understanding the call of asyncFunct() is asynchronous and therefore shouldn't print the warning message.

False.

Your call is not asynchronous. It is synchronous, because you have async: false.

This warning is because synchronous requests block the main thread (the same thread that handles UI, for example). This can ruin the user's experience using the site/app. Thus, the warning shows up in the console.

Community
  • 1
  • 1
Josh Beam
  • 19,292
  • 3
  • 45
  • 68
  • Thanks, this explains the warning, but could you explain WHY the call is synchronous? I've read http://stackoverflow.com/a/7374037/3298787 where it (to my understanding) says "calling a function with setTimeout() makes it asynchrounous" – Nijin22 Sep 07 '15 at 19:41
  • Thanks, this is a great answer. The reason I used a synchronous call is: I'll need to load translated messages from a json object (server-side, based on the clients `accept-language`, generated). I want to avoid making unnecessary calls to the object (--> cache it in "i18nObject"). To simplify this process I designated a single function for it: "i18n()" I will only need this function when I'm already de-synchronized from the main thread (--> asyncFunct()) and I'd like to avoid over-complication i18n() with a callback function – Nijin22 Sep 07 '15 at 21:30
  • @Nijin22, no prob. Okay that makes sense. I'm not sure off the top of my head of a better way to do it than what you're doing, but I would probably spend a bit of time investigating whether or not you can find a less "hacky"-feeling way of doing it. But the concept you're talking about makes sense (that is, caching the database object on the client). – Josh Beam Sep 07 '15 at 21:47
  • Thank you. I tried a lot of alternatives (generated & localized javascript, messages pre-loaded in the HTML, etc.) but haven't found one which works better than this with my current framework. I also dislike the current solution, but at least it is one which does work. – Nijin22 Sep 07 '15 at 21:52