How to make the calling function wait until the ca

2019-09-05 20:12发布

问题:

I have a button which when clicked opens a modal(dashboard_name) in which user enters some value. Based on the value after he clicks submit on that modal I call another function which opens another modal and user enters a different value there and finally when he clicks submit on this modal, I call an api to verify everything is correct.

Now, the problem is when I click on the first button to open the modal the execution doesn't wait for the function to get the data from the dashboard_name modal and then the graph_name modal. Instead it directly jumps to the api function call, which is right coz that's how jQuery works. But I wanted to know how to use deferred and promise to make this execution serial.

Function for the first button when clicked.

$('#add_to_dash').click(function(e){
  dashboard_submit();
  graph_submit();      
});

this function gets the dashboard modal and tries to get the value.

function dashboard_submit(){
  //do something
}

this function after success of the dashboard_submit function tries to get value for the graph modal

function graph_submit(){
  //do something
}

and then on form submit i call this following func

<form name="form2" onsubmit="return isDashboardCorrect(dashboard_name);" method="post" action="{{ url_for('dashboards_new') }}">

the function

function isDashboardCorrect(dashboard_name) {
  var flag=0;
  $.ajax({
    async: false,
    type: 'GET',
    url: 'xyz.com/dashboard/'+dashboard_name,
    success: function(data) {
      //alert(data);
      //do something
   });
}

I want all of this to be sequential which is not happening right now i.e. when i click on the first button it doesn`t wait for the functions to execute and directly the isdashboardcorrect() function gets called.

I want the order to be 1. button click 2. dashboard_submit() 3. graph_submit() 4. isdashboardcorrect() serially.

I tried something simpler like

$('#add_to_dash').click(function(e){
  alert('addtodashstart');
  dashboard_submit().done(function(){
    alert('done');
  });


  alert('addtodashend');
});


function dashboard_submit()
{
  alert('dashboardsubmot');
  var dfd = new $.Deferred();
  $("#d_name_modal_div").modal({backdrop: false}).modal("show");
  $('#d_name_modal_submit').on('click', function(){
    dashboard_name=$('#dashboard_name').val();
    alert(dashboard_name);
    if(dashboard_name==null || dashboard_name.trim()=='')
    {
      alert('Dashboard name is mandatory.');
      return false;
    }
    else
    {
      dfd.resolve();
      return dfd.promise();
    }
  });
}

When I click the button I call the dashboard_submit function. But here too it doesn`t wait for

`$('#d_name_modal_submit').on('click', function(){  

this to execute in the above function and directly hits the api function. What Am i doing wrong?`

Example fiddle : http://jsfiddle.net/LKP66/18/

回答1:

About your second question: You don't get it att all what I've explain it to you, do you?

done() subscription callbacks are called when you resolve your defferred instance dfd. It is called almost the very moment you resolve it. So you are going to open your next dialog when you have recieved the data.

Just take 1-2 hours and try to understand the concept and what I've explained to you. That is very poor programming you are doing there.

http://jsfiddle.net/qoytmgcj/2/

function dashboard_submit() {
     alert('Dashboard submit');
    var dfd = new $.Deferred();
    dashboard_name = 'ram';
     $("#d_name_modal_div").modal({
        backdrop: false
    });

    dfd.done(function(){
        var dn = $('#dashboard_name');
        dn.val('booooooo I recived the data now I can open the dialog');
        dn.text(dn.val());
        $("#d_name_modal_div").modal("show");
    });
    dfd.resolve();
    return dfd;
}

function wtf() {
    var dfd = $.Deferred();
    $('#d_name_modal_submit').on('click', function () {
        dashboard_name = $('#dashboard_name').val();
        alert(dashboard_name);
        if ( !$.trim(dashboard_name) ) {
            alert('Dashboard name is mandatory.');
            return false;
        } else {
            dfd.resolve();
            alert('success');
            return dfd;
        }
    });
} 


$('#add_to_dash').click(function (e) {

    alert('Add to dash start');
    dashboard_submit().done(function () {
        wtf();
    });
    alert('Add to dash end');
});


回答2:

  $('#add_to_dash').click(function(e) {

    $.when(dashboard_submit()).then(function(){
      graph_submit();
    });

  }); 

  function dashboard_submit() {
    var dfd = new $.Deferred();
    $.ajax({
      ....,
      ....,
      success: function (....) {
        dfd.resolve();
        /*some code...*/
      }
    });

    return dfd.promise();
  }

dfd is an object that can have a few outcomes same as $.ajax() which also returns deferred, actually. What are ajax outcome? success, error, complete.... and you have callbacks on them. Same thing with an instance of $.Deferred. However you have a control over what and when the outcome is resolve, reject,....etc. base on your code. As you can see I have receive successfully the data and I call that it was resolved successfully dfd.resolve();. So you can consider .then() and .done() equivalent to success both called on resolve. The difference is that then() is a method of dfd.promise().then() while done() is a method of dfd itself dfd.done()

Ex.2

  $('#add_to_dash').click(function(e) {

    dashboard_submit().done(function(){
      graph_submit();
    });

    /* That is 
     dfd.done(function(){
       graph_submit();
     });         
     since dashboard_submit() returns dfd
    */

  }); 

  function dashboard_submit() {
    var dfd = new $.Deferred();
    $.ajax({
      ....,
      ....,
      success: function (....) {
        dfd.resolve();
        /*some code...*/
      }
    });

    return dfd;
  }

Ex.3

As I mentioned $.ajax() returns $.Deferred instance so no need to create explicitly one so actually dfd isn't needed you are provided by one already so:

  $('#add_to_dash').click(function(e) {

    dashboard_submit().done(function(){
      graph_submit();
    });

  }); 

  function dashboard_submit() {
    return $.ajax({
      ....,
      ....,
      success: function (....) {

        /* The dfd that ajax returns is resolved on success by jQuery so no explicit instance creation is needed nor resolving*/
      }
    });
  }