3

I need to make a server side call when a user does something in the DOM (click a checkbox, select a dropdown, etc. This is the series of events:

  1. User clicks a checkbox (or something)
  2. A spinner fades in and the UI becomes unavailable
  3. The server side call is made, and gets back some JSON
  4. A label in the UI is updated with a value from the JSON
  5. The spinner fades out and the UI becomes available again

The problem I'm having is that 4 and 5 often get reversed, and the spinner fades out sometimes 2 or 3 seconds before the label is updated.

I'm trying to use .when() to make sure this isn't happening, but I don't seem to be doing it right. I've been looking at this thread, and this one, and jquery's own documentation.

Here's where I'm at right now...

function UpdateCampaign() {
    $('#overlay').fadeIn();
    $.when(SaveCampaign()).done(function () {
        $('#overlay').fadeOut();
    });
}

function SaveCampaign() {
    var formData =
        .... // get some data
    $.ajax({
        url: '/xxxx/xxxx/SaveCampaign',
        type: 'GET',
        dataType: 'json', 
        data: { FormData: formData },
        success: function (data) {
            var obj = $.parseJSON(data);
            .... // update a label, set some hidden inputs, etc.
        },
        error: function (e) {
            console.log(e)
        }
    });
}

Everything works correctly. The server side method is executed, the correct JSON is returned and parsed, and the label is updated as expected.

I just need that dang spinner to wait and fade out until AFTER the label is updated.

Community
  • 1
  • 1
Casey Crookston
  • 13,016
  • 24
  • 107
  • 193

2 Answers2

9

The issue is because you're not giving $.when() a promise. In fact you're giving it nullso it executes immediately. You can solve this by returning the promise that $.ajax provides from your SaveCampaign() function like this:

function SaveCampaign() {
    var formData = // get some data

    return $.ajax({ // < note the 'return' here
        url: '/xxxx/xxxx/SaveCampaign',
        type: 'GET',
        dataType: 'json', 
        data: { FormData: formData },
        success: function (data) {
            var obj = $.parseJSON(data);
            // update a label, set some hidden inputs, etc.
        },
        error: function (e) {
            console.log(e)
        }
    });
}
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
1

I know its answered by Rory already. But here's mine promise method, it works fine always and instead of using success and error uses done and fail

 var jqXhr = $.ajax({
    url: "/someurl",
    method: "GET",
    data: { 
      a: "a"
  });
//Promise method can be used to bind multiple callbacks
  if (someConditionIstrue) {
    jqXhr
    .done(function(data) {
      console.log('when condition is true', data);
    })
    .fail(function(xhr) {
      console.log('error callback for true condition', xhr);
    });
  } else {
    jqXhr.done(function(data){
      console.log('when condition is false', data);
    })
    .fail(function(xhr) {
      console.log('error callback for false condition', xhr);
    });
  }

Or if I want a common callback other than conditional ones, can bind directly on jqXhr variable outside the if-else block.

 var jqXhr = $.ajax({
    url: "/someurl",
    method: "GET",
    data: { 
      a: "a"
  });

  jqXhr
  .done(function(data) {
    console.log('common callback', data);
  })
  .fail(function(xhr) {
    console.log('error common back', xhr);
  });
Danish
  • 1,467
  • 19
  • 28