Jimmy Genslinger
Jimmy Genslinger

Reputation: 607

JQuery How when.done works

I'm really struggling with understanding how the when...done jquery event works. Below is a jsfiddle I created to show what's going on. I have two javascript functions, Main & subMain. The order of events I'm wanting to see on the results screen are:

Main Begin
SubMain Begin
SubMain End
Main End

Instead I see:

Main Begin
Main End
SubMain Begin
SubMain End

So what am I doing wrong? :(

JSFiddle

$(document).ready(function() {
    Main();
});

function Main() {
    $('#ajax').append("Main begin").append(['<br/>']);

    var jsonData = {
        "text1": "textData1",
        "text2": "textData2"
    };

    $.when(
        $.ajax({
            type: 'POST',
            dataType: 'json',
            url: '/echo/json/',
            data: {
                json: JSON.stringify(jsonData)
            },
            success: function(data) {
                //do Stuff
                var selected = "selected";

                if (selected.length > 0)
                    $.when(subMain()).done(function() {});
            }
        })
    ).done(function() {});

    $('#ajax').append("Main end").append(['<br/>']);
}

function subMain() {
    $('#ajax').append("subMain begin").append(['<br/>']);
    //do Stuff
    $('#ajax').append("subMain end").append(['<br/>']);
}

Upvotes: 0

Views: 145

Answers (2)

Supradeep
Supradeep

Reputation: 3266

As the definition in jQuery docs says about $.when,

Provides a way to execute callback functions based on zero or more objects, usually Deferred objects that represent asynchronous events.

The asynchronous events inside when in your code are $.ajax and $.when inside ajax success callback function. So, $.done will be called only after these two are resolved.

The problem in your code is with your 'Main end' statement. This is how the execution happens in your case :

  1. 'Main Begin' gets appended to the '#ajax' first.
  2. ajax call happens to the url you have mentioned which is asynchronous.
  3. Execution continues as ajax is async i.e the execution context doesn't wait for the ajax call to complete. As the next line after making the ajax call is 'Main end' statement, it is appended next.
  4. After the ajax call is successfully resolved, it calls the subMain method appending 'subMain begin' and 'subMain end'.

Hence, to get your code working as expected, move the 'Main end' statement inside the done callback function such that it'll be called after all the deferred objects inside when are resolved like this : Updated Fiddle

$.when(
    $.ajax(....)
).done(function() {
 $('#ajax').append("Main end").append(['<br/>']);
});

Upvotes: 2

kenarsuleyman
kenarsuleyman

Reputation: 1020

AJAX is an asynchronous function. You can set async to false in AJAX but it is deprecated.

Upvotes: 1

Related Questions