0

I have a jQuery function with several nested ajax calls:

function ulozitKlienta () {
  //some code
        if (!confirm("Není vyplněno datum vstupu klienta!\n\nPřesto uložit?")) return false;
  $.ajax({
    type    : "POST",
    cache    : false,
    url      : "ajax/ulozit_klienta.php",
    data    : JSON.stringify(out),
    dataType:  "json",
    success  : function (data) {
      if (data.vysledek == "chyba") {
        //some code
        return false;  // TODO ajax return
      } else {
        if (out["akce"] == "pridat") {
          if (data.vysledek == "duplikat") {
            $("#js-d-duplikat").dialog({
              modal    : true,
              buttons  : {
                "Přesto vytvořit nového"  :  function () {
                  out["opravdu"] = true;
                  $.ajax({
                    type    : "POST",
                    cache    : false,
                    url      : "ajax/ulozit_klienta.php",
                    data    : JSON.stringify(out),
                    dataType:  "json",
                    success  : function (data) {
                      if (data.vysledek == "chyba") {
                        //some code
                        return false;  // TODO ajax return
                      } else //some code
                    },
                    error    :  function (data, status, e) {
                      //some code
                      return false;  // TODO ajax return
                    }
                  });
                }
              }
            });
          } else //some code
        } else //some code
      }
    },
    error    :  function (data, status, e) {
      //some code
      return false;  // TODO ajax return
    }
  });
}

I have it in function because I call it from two different points elsewhere:

$("#add_tab").on("click", function() {  // založí nový protokol a vytvoří mu tab
  if (!ulozitKlienta()) return false;
  //some code
});

$("#menu_local").on("click", "[name='ulozit_klienta']", function() {
  ulozitKlienta();
});

My problem is, that function ulozitKlienta is not waiting for ajax calls to end and is returning undefined. I thought I use Promise interface as showed here https://stackoverflow.com/a/11283748/836697 but I really don't know how.

Community
  • 1
  • 1
meridius
  • 1,495
  • 1
  • 18
  • 26
  • 1
    http://stackoverflow.com/questions/3709597/wait-until-all-jquery-ajax-request-are-done – henrik Jul 23 '13 at 12:51
  • possible duplicate of [How to return the response from an AJAX call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call) – Alnitak Jul 23 '13 at 12:58
  • I can't use none of the provided answers. async:false is out of question. And using callbacks or promises as shown is not suitable for my case. I need to **define, NOT immediately use** the function once and use it at two different points in code which happen to be in .on(), so they're called based on interaction. I strongly believe that promises is the right way, I just don't know HOW. – meridius Jul 23 '13 at 14:31

2 Answers2

0

If you want to execute some code after ulozitKlienta finishes all async code try this: Change your function-header and call the callbacks at the end of the ajax-callbacks. This way you can define what should happen when ajax-call finishes.

function ulozitKlienta (successCallback, errorCallback) {
//some code
    if (!confirm("Není vyplněno datum vstupu klienta!\n\nPřesto uložit?")) return         false;
   $.ajax({
type    : "POST",
cache    : false,
url      : "ajax/ulozit_klienta.php",
data    : JSON.stringify(out),
dataType:  "json",
success  : function (data) {
  if (data.vysledek == "chyba") {
    //some code
    return false;  // TODO ajax return
  } else {
    if (out["akce"] == "pridat") {
      if (data.vysledek == "duplikat") {
        $("#js-d-duplikat").dialog({
          modal    : true,
          buttons  : {
            "Přesto vytvořit nového"  :  function () {
              out["opravdu"] = true;
              $.ajax({
                type    : "POST",
                cache    : false,
                url      : "ajax/ulozit_klienta.php",
                data    : JSON.stringify(out),
                dataType:  "json",
                success  : function (data) {
                  if (data.vysledek == "chyba") {
                    //some code
                    return false;  // TODO ajax return
                  } else //some code
                },
                error    :  function (data, status, e) {
                  //some code
                  return false;  // TODO ajax return
                }
              });
            }
          }
        });
      } else //some code
    } else //some code
  }
successCallback();
},
error    :  function (data, status, e) {
  errorCallback();
  //some code
  return false;  // TODO ajax return
}
});
 }

One last advice: Try to code and comment in English, it's easier to go through if one is not the coder itself ;-)

Jannik Weichert
  • 1,623
  • 16
  • 28
0

Your function should return the promise from $.ajax().

You then have to ensure that all subsequent processing is started from within a .done callback attached to that promise.

Nor can you return values from the jQuery dialog button callback functions. What you can do is return a promise that you've made yourself which you can .resolve when the button is pressed.

To clean up this code you actually need three functions, all of which should return a promise:

  • one for each of the two AJAX calls
  • one for the dialog box

and then chain together those three functions with something like this:

firstAjaxCall().then(function(data) {
    // test data - you can return `false` here if desired
    ...

    return showDialog().then(secondAjaxCall);
}).done(function() {
    // continue processing here
});
Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • Thank you for your suggestion, but I'm fairly new to promises and although I believe that it is the right way to do it - I don't know how to apply it on my case. I need to **define, NOT immediately use** the function once and use it at two different points in code which happen to be in .on(), so they're called based on interaction. I think that what you've suggested is immediately called. Could you please alter it for my case? – meridius Jul 24 '13 at 08:38
  • @meridius the code I've shown could be inside the `.on` handler. – Alnitak Jul 24 '13 at 08:40
  • well, that is my point. If I declare it in one .on() handler, I than would have to re-declare it in another, that's what I want to avoid. – meridius Jul 24 '13 at 11:26