2

I'm trying to send emails with a 10 seconds delay between. I wrote this code:

$(document).ready(function() {
    for (i = 0; i < 20; i++) {
        setTimeout("SendEmail(" + i + ")", 5000);
    }
});

function SendEmail(id) {
    $.get("mimesender.php?id=" + id, function(data) {
        var toAppend = "<span>     " + data + "</span>"
        $("#sentTo").append(toAppend);
    });
}

server side code(php) gets the id and selects the email with the specified id from the database

$query="select email from clienti where id =".$id;

then sends the email, and sends back the current email

echo email;

However, something is wrong here. It seems like the the js function waits for 5 seconds, and then displays all the 20 email addresses at once.

Can you tell me what I'm doing wrong ? any "sleep "workaround will be greatly appreciated :)

2
  • 1
    simply because your for loop doesn't wait the 5 seconds. Commented Dec 24, 2011 at 12:10
  • All the setTimeouts are basically called at the same time. Commented Dec 24, 2011 at 12:12

6 Answers 6

3

Use interval instead of loop.

Working demo: http://jsfiddle.net/xfVa9/2/

$(document).ready(function() {
    var tmr;
    var i=0;
    tmr=setInterval(function(){
        if(i<20){
            SendEmail(i);
            alert("Sent "+i)
            i++;
        }else{
            clearInterval(tmr);
        }

    },5000)

 });
Sign up to request clarification or add additional context in comments.

1 Comment

+1 for using setInterval. Be aware, though, that i is being declared as a global variable. Here's an improved example: jsfiddle.net/xfVa9/3
2

You should create a function which calls itself after 5 seconds

var i=0;

function sendEmailNow() {
     SendEmail(i);
     ++i;
   if(i<20) {
        setTimeout(sendEmailNow, 5000);
    }
}

2 Comments

@PointedEars Yes, it can be done. And I also agree global variables are evil but that is concern in JavaScript applications or webpage using much of JS code. Here I am not passing function construct (to avoid global variable) only for making it more readable (which is also desired).
This can be done without global i and without a function expression, see other answers. But function expressions are an important tool one should learn about.
2

What happens is that you call setTimeout 20 times, just after one another, with a timeout of 5 seconds. So naturally, all emails gets sent at once. You could change the loop to look like this:

for (i=0;i<20;i++) {
    setTimeout("SendEmail("+ i + ")",(i+1)*5000);
}

There's alot of other options though, and they'd depend on just what suits your specific problem best.

Comments

2

First, pass a function to setTimeout.

Secondly, you'd be better off if you set the timeout for the next one in the queue after the current one is finished.

In the for loop:

sendEmail(0); // start sending first

and in the callback:

      , function(data) {
          if(id < 19) { // if next should be sent
              setTimeout(function() {
                  SendEmail(id + 1);
              }, 5000);
          }
          var toAppend = "<span>     " + data + "</span>"
          $("#sentTo").append(toAppend);
      }

Comments

1

Your loop is setting up 20 timers to wait 5 seconds, then letting them all go at once.

Try something like this:

var email_count = 20;

var sendMails = function(){
    SendEmail(email_count--);
    if(email_count > 0){
        setTimeout(sendMails, 5000);
    }
}

setTimeout(sendMails, 5000)

Comments

0
  1. Avoid jQuery. Learn JavaScript.
  2. var i = 0; (otherwise leak into outer scope or runtime error)
  3. Extra closure:

    window.setTimeout(
      (function (j) {
         return function () {
           sendEmail(j);
         };
       }(i)),
      i * 10000);
    
  4. sendEmail (code style: not a constructor)
  5. You really want to escape $id in the server-side code to prevent SQL injection.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.