3

I have a jquery function for sending email with ajax request;

function sendMail(from,to,subject,message){
    var datastr="from="+from+"&to="+to+"&subject="+subject+"&message="+message;
    $.ajax({
        type: "POST",
        url: "mail.php",
        data: datastr,
        cache: false,
        success: function(html){
            return true;
        },
        error: function(jqXHR,status,error){
            return false;
        }
    });
}

now I want to tell the user if the mail was successfully sent or not like this:

$("#feedback").html("Sending email...");
if(sendMail("from@email.com","to@email.com","MySubject","MyMessage"))
   $("#feedback").html("Email sent.");
else
   $("#feedback").html("Error sending email.");

but of course jQuery processes the if condition before the mail was sent, so the condition is false :-( How do I tell jQuery to wait until sendMail has completed and returns something?

Thiezar
  • 1,143
  • 2
  • 10
  • 16

3 Answers3

8

While the given answers are valid, I would consider keeping the sendmail function and the DOM modifications separate (i.e. keeping $("#feedback").html... out of the success/error callbacks ). You can do this by returning the result of the ajax call:

function sendMail(from,to,subject,message){
    var datastr="from="+from+"&to="+to+"&subject="+subject+"&message="+message;
    return $.ajax({
        type: "POST",
        url: "mail.php",
        data: datastr,
        cache: false
    });
}

The return value implements the Promise interface, so you can then do this:

$("#feedback").html("Sending email...");
sendMail("from@email.com","to@email.com","MySubject","MyMessage")
    .done(function(){
        $("#feedback").html("Email sent.");
    })
    .fail(function(){
        $("#feedback").html("Error sending email.");
    });

Note that I removed the success and error fields from the ajax call since they're not needed, but you could still use them if you need them for something else, like logging.

Supr
  • 18,572
  • 3
  • 31
  • 36
  • You got what I'm looking for but this doesn't work :-( It throws this error "Cannot call method 'done' of undefined". I think method done should be used only on deferred objects. – Thiezar Jul 01 '12 at 17:22
  • I found this solution: `$.when(sendMail("from@email.com","to@email.com","MySubject","MyMessage")) .done(function(){ $("#feedback").html("Email sent."); }) .fail(function(){ $("#feedback").html("Error sending email."); });` but there is a problem: the done and fail methods check if sendMail function successes or not, not if it returns true or false, so even if it returns false it throws "email sent" :-( – Thiezar Jul 01 '12 at 17:35
  • Regarding your first comment, did you change the `sendMail` function too so that it returns the result from the ajax call? Regarding your second comment, if you didn't change your `sendMail` function then it will always return `undefined`, which `$.when` treats as a "successful" value. Either version should work if you changed the line `$.ajax({` to `return $.ajax({`. – Supr Jul 01 '12 at 17:59
  • Oops! My fault. Didn't see that return before $.ajax :-p In this case your solution works just great. Thank you very much. You helped me a lot. – Thiezar Jul 02 '12 at 12:52
0
$("#feedback").html("Sending email...");
$.ajax({
    type: "POST",
    url: "mail.php",
    data: datastr,
    cache: false,
    success: function(html){
       if (sendMail("from@email.com","to@email.com","MySubject","MyMessage")) {
          $("#feedback").html("Email sent.");
       } else {
          $("#feedback").html("Error sending email.");
       }
    },
    error: function(jqXHR,status,error){
        $("#feedback").html("Error sending email.");
    }
});

don't know what sendMail is, but if that's your check to see if the e-mail was sent, so be it ?

adeneo
  • 312,895
  • 29
  • 395
  • 388
0

It is not possible for your sendMail function to return true/false based on the results of an AJAX call (unless you use synchronous requests, wich is almost always a terrible idea). This is just the way JavaScript in a browser works, and for good reasons that I won't get into here.

Instead, you have to tell $.ajax what to do in the even of succeeding or failing.

One way to do that looks like this:

$.ajax({
  // omitting arguments for clarity
  success: function(){
    $("#feedback").html("Email sent.");
  },
  error: function(){
    $("#feedback").html("Error sending email.");
  }
});
nicholaides
  • 19,211
  • 12
  • 66
  • 82