clearInterval() not working correctly

2019-09-04 05:25发布

问题:

I've recently been trying to repeat a jQuery AJAX request every two seconds. PLEASE NOTE: I've looked at the other questions on SO and not of them seem to apply to my situation, i've also looked at the documentation.

Snippet:

else if (text == "load") {
        $(".response").text("working!");

        var traffic = function load() {
            $.ajax({url:"load.php",success:function(result){
                var obj = jQuery.parseJSON(result);
                var ids = obj.map(function(el) {
                    return "<tr><td>" + el.id + "</td><td>" + el.ip + "</td><td>" + el.proxyip + "</td><td>" + el.ping + "</td><td>" + el.time + "</td></tr>";
                });

                $(".response").html("<table><tr><td><strong>ID</strong></td><td><strong>IPs</strong></td><td><strong>Proxy IP</strong></td><td><strong>Ping</strong></td><td><strong>Time</strong></td></tr>" + ids + "</table>");
            }});
        };

        var trafficInterval = setInterval(traffic, 2000);

To cancle the timeout, i check to see if the text is not equal to "load", if it isnt equal to load, i cancle the timeout

else {
        $(".response").text("'" + badCommand + "'" +" is not a valid command, type 'help' for a list of commands.");
        clearInterval(trafficInterval);
    }

HOWEVER, when i change the input of the textfield, the table will still load every two seconds, the timeout hasn't been cancled and i can't seem to see why.

Here's the whole function for people wondering

$("textarea").keyup(function(){
var text = $(this).val();
$(".log").text(text);

// Commands
if (text != "") {
    var badCommand = $("textarea").val();

    if (text == "help") {
        $(".response").html("Commands:<br/><span class='indent'>traffic -url|all</span><span class='indent'>google #search term</span><span class='indent'>youtube #search term</span><span class='indent'>portfolio</span>")
    } else if (text == "traffic") {
        $(".response").html('Live traffic from:<br/><table><tr><td><strong>IP</strong></td><td><strong>Proxy IP</strong></td><td><strong>Ping</strong></td><td><strong>Time</strong></td></tr><?php try { $db = new PDO("mysql:host=$mysql_host;dbname=$mysql_db", $mysql_user, $mysql_pass); $sql = "SELECT * FROM traffic ORDER BY id DESC LIMIT 50"; foreach ($db->query($sql) as $row) { echo "<tr>"; echo "<td class='details'>" . $row["ip"] . "</td>"; echo "<td class='details'>" . $row["proxyip"] . "</td>"; echo "<td class='details'>" . $row["ping"] . "</td>"; echo "<td class='details'>" . $row["time"] . "</td>"; echo "</tr>"; } $db = null; } catch(PDOException $e) { $e->getMessage(); } ?></tr></table>');
    } else if (text == "load") {
        $(".response").text("working!");

        var traffic = function load() {
            $.ajax({url:"load.php",success:function(result){
                var obj = jQuery.parseJSON(result);
                var ids = obj.map(function(el) {
                    return "<tr><td>" + el.id + "</td><td>" + el.ip + "</td><td>" + el.proxyip + "</td><td>" + el.ping + "</td><td>" + el.time + "</td></tr>";
                });

                $(".response").html("<table><tr><td><strong>ID</strong></td><td><strong>IPs</strong></td><td><strong>Proxy IP</strong></td><td><strong>Ping</strong></td><td><strong>Time</strong></td></tr>" + ids + "</table>");
            }});
        };

        var trafficInterval = setInterval(traffic, 2000);

    } else {
        $(".response").text("'" + badCommand + "'" +" is not a valid command, type 'help' for a list of commands.");
        clearInterval(trafficInterval);
    }
}

if (text == "") {
    var noCommand = $("textarea").val();
    $(".response").text(" ");
}

// End Commands

});

FYI:

Putting the clearInterval(); AFTER the code stops it from working,
Putting the clearInterval(); BEFORE the code does nothing.

The clearInterval(trafficInterval); MUST be working because if i place it at the end of the first function, nothing happens when i type "load"

It's not the timer either, i tried it instead to automatically update whenever the mouse is moved and the exact same thing happens...

回答1:

This is a scoping issue. The interval needs to be outside the scope of the event handler call:

var trafficInterval = null;
$("textarea").keyup(function(){
var text = $(this).val();
$(".log").text(text);

// Commands
if (text != "") {
    var badCommand = $("textarea").val();

    if (text == "help") {
        $(".response").html("Commands:<br/><span class='indent'>traffic -url|all</span><span class='indent'>google #search term</span><span class='indent'>youtube #search term</span><span class='indent'>portfolio</span>")
    } else if (text == "traffic") {
        $(".response").html('');
    } else if (text == "load") {
        $(".response").text("working!");

        var traffic = function load() {
            $.ajax({url:"load.php",success:function(result){
                var obj = jQuery.parseJSON(result);
                var ids = obj.map(function(el) {
                    return "<tr><td>" + el.id + "</td><td>" + el.ip + "</td><td>" + el.proxyip + "</td><td>" + el.ping + "</td><td>" + el.time + "</td></tr>";
                });

                $(".response").html("<table><tr><td><strong>ID</strong></td><td><strong>IPs</strong></td><td><strong>Proxy IP</strong></td><td><strong>Ping</strong></td><td><strong>Time</strong></td></tr>" + ids + "</table>");
            }});
        };

        trafficInterval = setInterval(traffic, 2000);

    } else {
        $(".response").text("'" + badCommand + "'" +" is not a valid command, type 'help' for a list of commands.");
        clearInterval(trafficInterval);
    }
}

if (text == "") {
    var noCommand = $("textarea").val();
    $(".response").text(" ");
}

// End Commands
});

See fiddle @ http://jsfiddle.net/sLooj4on/ (can see polling fail in dev tools, stops when text is removed from input)



回答2:

It's hard to tell without looking at the rest of the code, but your trafficInterval variable could be out of scope. Try initializing outside of the if/else statement



回答3:

trafficInterval is only defined within the if statement. You're trying to clear it in the wrong scope. I still lack a bit of context here but you can try this:

var trafficInterval;
$("textarea").keyup(function() {
      var text = $(this).val();
      $(".log").text(text);

      // Commands
      if (text != "") {
        var badCommand = $("textarea").val();

        if (text == "help") {
          $(".response").html("Commands:<br/><span class='indent'>traffic -url|all</span><span class='indent'>google #search term</span><span class='indent'>youtube #search term</span><span class='indent'>portfolio</span>")
        } else if (text == "traffic") {
          $(".response").html('Live traffic from:<br/><table><tr><td><strong>IP</strong></td><td><strong>Proxy IP</strong></td><td><strong>Ping</strong></td><td><strong>Time</strong></td></tr><?php try { $db = new PDO("mysql:host=$mysql_host;dbname=$mysql_db", $mysql_user, $mysql_pass); $sql = "SELECT * FROM traffic ORDER BY id DESC LIMIT 50"; foreach ($db->query($sql) as $row) { echo "<tr>"; echo "<td class='
            details '>" . $row["ip"] . "</td>"; echo "<td class='
            details '>" . $row["proxyip"] . "</td>"; echo "<td class='
            details '>" . $row["ping"] . "</td>"; echo "<td class='
            details '>" . $row["time"] . "</td>"; echo "</tr>"; } $db = null; } catch(PDOException $e) { $e->getMessage(); } ?></tr></table>');
        } else if (text == "load") {
          $(".response").text("working!");

          var traffic = function load() {
            $.ajax({
              url: "load.php",
              success: function(result) {
                var obj = jQuery.parseJSON(result);
                var ids = obj.map(function(el) {
                  return "<tr><td>" + el.id + "</td><td>" + el.ip + "</td><td>" + el.proxyip + "</td><td>" + el.ping + "</td><td>" + el.time + "</td></tr>";
                });

                $(".response").html("<table><tr><td><strong>ID</strong></td><td><strong>IPs</strong></td><td><strong>Proxy IP</strong></td><td><strong>Ping</strong></td><td><strong>Time</strong></td></tr>" + ids + "</table>");
              }
            });
          };

          trafficInterval = setInterval(traffic, 2000);

        } else {
          $(".response").text("'" + badCommand + "'" + " is not a valid command, type 'help' for a list of commands.");
          clearInterval(trafficInterval);
        }
      }

      if (text == "") {
        var noCommand = $("textarea").val();
        $(".response").text(" ");
      }

      // End Commands



回答4:

Move the variable declaration

var trafficInterval = null;

before the keyup eventhandler (to move it to the outside scope). See working, stripped down example here:

http://jsbin.com/yitiquwoce/1/