【问题标题】:javascript sleep with SetTimeout使用 SetTimeout 的 javascript 睡眠
【发布时间】:2011-12-24 12:07:16
【问题描述】:

我正在尝试以 10 秒的延迟发送电子邮件。我写了这段代码:

$(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);
    });
}

服务器端代码(php) 获取 id 并从数据库中选择具有指定 id 的电子邮件

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

然后发送邮件,并将当前邮件发回

echo email;

但是,这里出了点问题。好像js函数等待5秒,然后一次显示所有20个电子邮件地址。

你能告诉我我做错了什么吗?任何“睡眠”解决方法将不胜感激:)

【问题讨论】:

  • 只是因为你的 for 循环不会等待 5 秒。
  • 所有setTimeouts基本上是同时调用的。

标签: javascript jquery ajax settimeout


【解决方案1】:

使用区间而不是循环。

工作演示: 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)

 });

【讨论】:

  • +1 用于使用setInterval。但请注意,i 被声明为全局变量。这是一个改进的示例:jsfiddle.net/xfVa9/3
【解决方案2】:

你应该创建一个在 5 秒后调用自己的函数

var i=0;

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

【讨论】:

  • @PointedEars 是的,可以做到。而且我也同意全局变量是邪恶的,但这在使用大量 JS 代码的 JavaScript 应用程序或网页中是值得关注的。在这里,我传递函数构造(以避免全局变量)只是为了使其更具可读性(这也是需要的)。
  • 这可以在没有全局 i 并且没有函数表达式的情况下完成,请参阅其他答案。但函数表达式是一个值得学习的重要工具。
【解决方案3】:

发生的情况是您调用 setTimeout 20 次,一个接一个,超时时间为 5 秒。所以很自然,所有电子邮件都会立即发送。您可以将循环更改为如下所示:

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

不过还有很多其他选项,它们取决于最适合您的特定问题的选项。

【讨论】:

    【解决方案4】:

    首先,将函数传递给setTimeout

    其次,如果您在当前队列完成后为队列中的下一个队列设置超时,您会更好。

    for 循环中:

    sendEmail(0); // start sending first
    

    在回调中:

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

    【讨论】:

      【解决方案5】:

      您的循环设置了 20 个计时器以等待 5 秒,然后立即让它们全部运行。

      试试这样的:

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

      【讨论】:

        【解决方案6】:
        1. 避免使用 jQuery。学习 JavaScript。
        2. var i = 0;(否则泄漏到外部作用域或运行时错误)
        3. 额外的关闭:

          window.setTimeout(
            (function (j) {
               return function () {
                 sendEmail(j);
               };
             }(i)),
            i * 10000);
          
        4. sendEmail(代码风格:不是构造函数)
        5. 您确实想在服务器端代码中转义 $id 以防止 SQL injection

        【讨论】:

          猜你喜欢
          • 2013-08-17
          • 2020-06-15
          • 1970-01-01
          • 2011-11-29
          • 1970-01-01
          • 2011-08-15
          • 2012-04-02
          • 1970-01-01
          • 2019-10-21
          相关资源
          最近更新 更多