Home Why does async: false inside a listener, stop all execution?
Reply: 1

Why does async: false inside a listener, stop all execution?

juju
1#
juju Published in 2017-12-07 16:25:41Z

I've been staring at this issue for a few hours. I had a boilerplate code sample I was working off as follows

$('.save_stuff').on("click", function(e) 
{
    e.preventDefault();
    e.stopPropagation();

    preprocessAddProvisioning();

    var mac = $('#c_mac_address').val();
    var make = $('#c_make').html();
    var model = $('#c_model option:selected').text();
    var regex = /[a-zA-Z0-9]{12}/g;

    if (mac.match(regex) && validateNewDevice())
    {
        $.ajax({
            url: "/SomeUrl",
            dataType: 'json',
            type: 'POST',
            async: false,
            data: 
            {
                mac: mac,
                model: model,
                make: make
            },
            success: function(data)
            {
                if (data.success)
                {
                    $('#someValue').hide();
                    $('#modalNewDevice').modal('hide');

                    if (someValue !== undefined && !someValue.snom_mac_success)
                    {
                        window.location.href = "/SomeUrl?id="+someValue.newId+"&someValue=false";
                    }
                    else
                    {
                        window.location.href = "/SomeUrl?id="+data.newId;
                    }
                }
                else
                {
                    $('#c_msg').html(data.msg);
                    $('#c_msg').closest('.form-group').addClass('has-error');
                }
            },
            error: function()
            {

            }
        });
    }
});

With the method called being;

function preprocessAddProvisioning()
{
    $('#mac_load').show('fast');
}

Can someone tell me why, async: false, stops preprocessAddProvisioning() being called? I realize it's implication when thinking about the context of the ajax request, but not of the context of the listener.

Many thanks

JLRishe
2#
JLRishe Reply to 2017-12-07 17:12:01Z

The AJAX request doesn't prevent preprocessAddProvisioning() from executing. It blocks the UI thread and prevents the window from updating, so it appears that preprocessAddProvisioning() has done nothing. On top of that, .show('fast') uses an animation, which would require not just one UI update, but many over a period of several milliseconds. With the JavaScript execution stopped, jQuery can't even try to carry out that animation, let alone have the window display it.

Demonstration of a window failing to update due to a blocked UI thread:

document.getElementsByTagName('input')[0].addEventListener('click', function (){
    var div = document.getElementsByTagName('div')[0];
    // hide div
    div.style.display = 'none';
    
    // block thread for 3 seconds
    var dt = new Date();
    while (new Date() - dt < 3000) {}
});
div { width: 100px; height: 100px; background-color: red; }
<div>

</div>
<input type="button" value="Click me" />

Moral of the story: don't use async: false, but if you absolutely have to, you can use a timeout to ensure that your loader has finished displaying before you make the AJAX request:

setTimeout(function () {
    makeTheAjaxRequest();
}, 500);

Bear in mind that if your loader involves an animated .gif or anything like that, the .gif will be frozen while the UI thread is blocked.

An even more precise option would be to use the complete callback on .show() to continue executing your steps once the animation is complete, but all that's likely to accomplish is spaghetti-fying your code. The real answer is to not use async: false.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.322785 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO