Nick
Nick

Reputation: 2922

Tactics to avoid using async:false with jQuery?

The jQuery docs strongly urge you not to set async to false when performing an $.ajax request.

However, I'm seeing common solutions to synchronicity problems involve doing just this. And then I've seen people been chastised for going against the docs' recommendation.

With that said, I have attempted to use a promise to avoid using async:false with no luck.

Here is the code I'm using. I have an onclick event that calls addToOrder:

function saveTemplate() {
    var formData = getFormData();
    return $.ajax({
        type: "POST",
        url: "/p/session/save/" + sessionid + "/template/<?php echo $templateID ?>/",
        data: formData,
        async: true,
        success: function(msg){
            var rsp = $.parseJSON(msg);
            if (rsp.response === 'Saved') {
                sessionid = rsp.sessionid;
                $("#save-preview-data-response").html("&nbsp;&nbsp;&nbsp;" + rsp.response).fadeIn(100).delay(1000).fadeOut(1000);
            } else {
                $("#save-preview-data-response").css('color','#ff0000').html("&nbsp;&nbsp;&nbsp;" + rsp.response).fadeIn(100).delay(1000).fadeOut(1000);
            }
        }
    });
}

function addToOrder() {
    var saved = saveTemplate();
    var issaved;
    saved.success(function(e) {
        var rsp = $.parseJSON(e);
        issaved = (rsp.response == 'Saved') ? true : false;
    });
    if(issaved) {
        $.ajax({
            type: "POST",
            url: "<?php echo $baseURL; ?>addToOrder/respond/json",
            data: "sid=" + sessionid,
            async: true,
            success: function(msg){
                var rsp = $.parseJSON(msg);
                if (rsp.response === 'Saved') {
                    alert(msg);
                }
            }
        });
    }
}

issaved will always evaluate to false, as it is being evaluated before saveTemplate has had time to run. The only solution I have found is to set async:false but I am taking the warnings I've seen serious and would rather not. What other solutions are there?

Upvotes: 5

Views: 4070

Answers (3)

Chris
Chris

Reputation: 27609

You could change the SaveTemplate function to accept a parameter that is a function that is run on save. Then in your addToOrder function you can either generate an anonymous function with the code you have in there or refactor so that most of that code is in another function that you can pass by name.

The idea is that with async code the moment you make an async call you stop working on that issue there (ie the save code) and pick up running in your callback. You could keep doing unrelated stuff after the async call (eg putting up a message to the user sayign "please wait") but any further code related to the save must be in a function triggered by the callback set in the success property of the ajax configuration.

Upvotes: 1

T.J. Crowder
T.J. Crowder

Reputation: 1074485

Tactics to avoid using async:false with jQuery?

Learn to love callbacks. :-) When people do this:

// The synchronous way
function doSomething() {
    var foo;
    $.ajax({
        url: "/the/url",
        async: false,
        success: function(response) {
            foo = response.foo;
        }
    });
    return foo;
}

// ...somewhere else, we use it
function flurgle() {
    var bar = /* go get `bar` from somewhere */;
    var x = 52;

    if (doSomething() === bar) {
        x -= 10;
    }
    niftyFunctionUsing(x);
}

...the event-driven, asynchronous way really isn't that much different:

// The asynchronous way
function doSomething(callback) {
    $.ajax({
        url: "/the/url",
        success: function(response) {
            callback(response.foo);
        }
    });
}

// ...somewhere else, we use it
function flurgle() {
    var bar = /* go get `bar` from somewhere */;
    var x = 52;

    doSomething(function(foo) {
        if (foo === bar) {
            x -= 10;
        }
        niftyFunctionUsing(x);
    });
}

Since callbacks frequently involve closures (the above ones do, that's how we're accessing x and bar), this article from my blog may be helpful: Closures are not complicated

Upvotes: 12

evan
evan

Reputation: 4297

Put the second .ajax() call inside of the .success() function of the first.

Upvotes: 0

Related Questions