【问题标题】:setTimeout only runs once in loopsetTimeout 只在循环中运行一次
【发布时间】:2015-02-05 02:54:40
【问题描述】:

我的目标是每 X 秒执行一次 javascript 函数。我读过应该使用 setInterval ,但在我的情况下我不相信。我也不希望必须重新发送变量,以防用户决定在正式发送所有内容之前更改内容

例如,我输入了 60 个时间和 5 个数量,但它等待了 60 秒,然后只发送了 5 个,每 60 秒发送 1 个文本,直到它发送了 5 个文本

我的 javascript

    $('input[name="sendtxt"]').click(function(e) {
        sendText(e);
    });

function sendText(e) {
    e.preventDefault();
    var phonenum = $('input[name="phonenum"]').val();
    var provider = $('select[name="provider"]').val();
    var message = $('textarea[name="message"]').val();
    var otherprov = $('input[name="otherprov"]').val();
    var amount = $('input[name="amount"]').val();
    var time = $('input[name="time"]').val() * 1000;
    var sendmsg;
    for (sendmsg = 1; sendmsg <= amount; sendmsg++) {
        setTimeout(function() {
            $.ajax({
                type: 'POST',
                data: {
                    provider: provider,
                    message: message,
                    phonenum: phonenum,
                    amount: amount,
                    otherprov: otherprov,
                    time: time
                },
                url: 'send.php',
                success: function(data) {
                    console.log('Success. Sent ' + sendmsg + " texts.");
                },
                error: function(xhr, err) {
                    console.log("readyState: " + xhr.readyState + "\nstatus: " + xhr.status);
                    console.log("responseText: " + xhr.responseText);
                }
            });
        }, time);
    }

还有我的 PHP

<?php


$to = $_POST["phonenum"];
$provider = $_POST["provider"];

$otherprov = $_POST["otherprov"];
$fixedotherprov = str_replace("otherprovider", "", $otherprov);


$completenum = $to . $provider . $fixedotherprov;
$completenum = str_replace('otherprovider', '', $completenum);
$subject = 'Hello';
$message = $_POST["message"];
$headers = 'From: Daniel';
$amount = $_POST["amount"];

//for ($x = 0; $x < $amount; $x++) {
    mail($completenum, $subject, $message, $headers);
//}

?>

【问题讨论】:

  • 注意:setTimeout 将在单线程中运行

标签: javascript php jquery for-loop settimeout


【解决方案1】:

setTimeout是一个异步函数。超时事件在您的循环中定义,从sendmsg = 1sendmsg &lt;= amount。执行 for 循环后,将执行 for 循环下方的其余代码,直到触发 timeout 事件。当触发超时事件时,sendmsg 的值等于amount+1,因为循环已经完成执行。因此,所有超时事件的值都是 sendmsgas amout+1 导致意外行为..

在下面的代码中,每次迭代都会定义一个临时范围,它为每个 timeout 事件提供不同的 sendmsg 值。

您还必须在每次迭代中安排不同的时间作为超时时间值,以便在不同的超时时间内执行它们。

像这样修改你的代码..

function sendText(e) {
    e.preventDefault();
    var phonenum = $('input[name="phonenum"]').val();
    var provider = $('select[name="provider"]').val();
    var message = $('textarea[name="message"]').val();
    var otherprov = $('input[name="otherprov"]').val();
    var amount = $('input[name="amount"]').val();
    var time = $('input[name="time"]').val();
    var sendmsg;
    for (sendmsg = 1; sendmsg <= amount; sendmsg++) {
            (function(sendmsg){
               setTimeout(function() {
                $.ajax({
                    type: 'POST',
                    data: {
                        provider: provider,
                        message: message,
                        phonenum: phonenum,
                        amount: amount,
                        otherprov: otherprov,
                        time: time * 1000 * sendmsg
                    },
                    url: 'send.php',
                    success: function(data) {
                        console.log('Success. Sent ' + sendmsg + " texts.");
                    },
                    error: function(xhr, err) {
                        console.log("readyState: " + xhr.readyState + "\nstatus: " + xhr.status);
                        console.log("responseText: " + xhr.responseText);
                    }
                });
            }, time * 1000 * sendmsg);
           })(sendmsg);
        }
}

【讨论】:

  • 我把你的代码放进去,我相信现在它会等到时间,但之后它会一次性发送金额。我不确定我是否清楚,但目标是让它发送大量文本,每次几秒钟一次 1 条文本
  • 那么您必须在每次迭代时更改超时函数中使用的时间值。我更改了代码。检查它现在是否有效..
【解决方案2】:

这是范围问题。

阅读有关 Javascript 闭包(作用域)函数的更多信息:http://brackets.clementng.me/post/24150213014/example-of-a-javascript-closure-settimeout-inside

将您的代码更改为:

for (sendmsg = 1; sendmsg <= amount; sendmsg++) {
    (function(){
        setTimeout(function(_provider, _message, _phonenum, _amount, _otherprov, _time, _sendmsg) {
            $.ajax({
                type: 'POST',
                data: {
                    provider: _provider,
                    message: _message,
                    phonenum: _phonenum,
                    amount: _amount,
                    otherprov: _otherprov,
                    time: _time
                },
                url: 'send.php',
                success: function(data) {
                    console.log('Success. Sent ' + _sendmsg + " texts.");
                },
                error: function(xhr, err) {
                    console.log("readyState: " + xhr.readyState + "\nstatus: " + xhr.status);
                    console.log("responseText: " + xhr.responseText);
                }
            });
        }, time);
    })(provider, message, phonenum, amount, otherprov, time, sendmsg);
}

希望有帮助。

【讨论】:

  • 1.当您说要更改我的代码时,您的意思只是 for 循环,而不是整个事情,对吗? 2. 我不太清楚你为什么把 _ 放在前面?
  • 只需用我提供的代码更改您的整个for 代码,其中包括一个具有本地内部变量(_provider、_message 等)的作用域函数。 - 除此之外你不需要改变任何东西。
  • 我把你的代码放进去,我相信现在它会等到time,但之后它会一次性发送amount。我不确定我是否清楚,但目标是发送 amount 的文本,每 time 秒一次发送 1 条文本
  • 例如,我输入了 60 个时间和 5 个数量,但它等待了 60 秒,然后只发送了 5 个,每 60 秒发送 1 个文本,直到它发送了 5 个文本
猜你喜欢
  • 1970-01-01
  • 2011-12-13
  • 2017-01-24
  • 1970-01-01
  • 2018-05-02
  • 1970-01-01
  • 2019-09-04
  • 2011-11-02
  • 2013-11-28
相关资源
最近更新 更多