延迟后执行函数或在jquery中终止它

时间:2018-01-09 16:22:37

标签: javascript jquery ajax

我使用一个函数来加载一个带有jQuery的页面,但只是在将鼠标悬停在li之后的一段时间之后。为此,我在setTimeout上使用mouseover,如果鼠标在mouseleave上徘徊不到500毫秒,请尝试在li上将其删除。但是,jQuery.ajax仍会启动,所以基本上,如果我将鼠标悬停在所有li上,即使我只在li停留1毫秒,也会启动大量的xhr。

var timer2;
var delay2 = 500;

$('body').on('mouseover','li',function(){

    timer2 = setTimeout(function() {

        var url="res.php";
            jQuery.ajax(
            {
                type: 'POST',
                url:url,
                success: function(data){

                    $('#res').html(data);

                }
            });


    }, delay2);

});
$('body').on('mouseleave', 'li', function() {
    clearTimeout(timer2);
});

4 个答案:

答案 0 :(得分:3)

在再次设置之前,请先清除超时时间:

var timer2 = null;

$('body').on('mouseover','li',function(){
    clearTimeout(timer2);
    timer2 = setTimeout(function(){ .....

您需要将超时初始化为null,否则您将收到错误can't clear timeout of undefined

另外,试试这个来触发mouseleave:

$('body').on('mouseover','li',function(){
     // ...
     $(this).off("mouseleave").on("mouseleave", () => clearTimeout(timer2))
});

修改:工作代码段

var timer2 = null;
var delay2 = 2000;

$('body').on('mouseover', 'li', function() {
  clearTimeout(timer2);
  console.log("Setting timeout...")

  timer2 = setTimeout(() => console.log("Ajax call!"), delay2);

  $(this).off("mouseleave").on('mouseleave', () => {
    console.log("Clearing timeout.")
    clearTimeout(timer2);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<li>Hover over me</li>
<li>Over me too</li>

答案 1 :(得分:3)

这里的问题很简单。您使用鼠标悬停,当您在元素上时,鼠标悬停可以触发多个setTimeouts。

$("div")
  .on("mouseover", function(){ console.log("mouseover"); })
  .on("mouseenter", function(){ console.log("mouseenter"); });
span { background-color: red;
font-size: 2em;
} 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <span>Move mouse here</span> to <span>here</span> to <span>here</span></div>

因此,每次移动父级内部的元素时,都会触发另一次鼠标悬停。因此,如果是这种情况,您将创建多个事件。因此,如果您看到多个ajax调用li,那可能就是原因。

因此将其更改为mouseenter,接下来取消输入中的事件或通过li本身跟踪事件而不是全局。

$("ul")
  .on("mouseenter", "li" function(){ 
    $(this).data("timer", setTimeout( function () {});
  }).on("mouseleave", "li" function(){ 
    var id = $(this).data("timer");
    if (id) window.clearTimeout(id);
  })

如果你真的想确定,请清除mouseenter上的超时....

答案 2 :(得分:-1)

为该特定id提供li,并使用如下方式。这有效。查看console Networks标签进行验证。

var timer2;
var delay2 = 500;
var ajax;
$('body').on('mouseover','li#one',function(){
    console.log("Mouse over");
    clearTimeout(timer2);
    timer2 = setTimeout(function() {
        if(ajax) {ajax.abort();}
        var url="res.php";
        ajax = $.ajax(
        {
            type: 'POST',
            url:url,
            async:true,
            success: function(data){
                $('#res').html(data);
            }
        });
    }, delay2);

});
$('body').on('mouseleave', 'li#one', function() {
    console.log("Mouse left");
    clearTimeout(timer2);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<li id="one">One</li>
<li>Two</li>

答案 3 :(得分:-1)

解决此问题的方法很少

    abort 之后
  1. mouseleave您的请求
  2. 在回调中使用变量告诉它“不要这样做”
  3. abort您的请求

    // ...
    var request;
    
    $('body').on('mouseover','li',function(){
        // ... I omited `setTimeout` to simplify the explanation
        // you have to make this variable to be able to control your requests
        var xhr = new window.XMLHttpRequest();
        // here we save our request
        request = jQuery.ajax(
                {
                    // ...
                    // note this change here, it is required for jquery 3.0 and more
                    xhr : function(){ return xor; }
                });
        // ...
    
    });
    $('body').on('mouseleave', 'li', function() {
        // ...
        // now we can `abort` it any time user mouse leaves
        request.abort();
    });
    

    Question about abort on SO

    使用变量

    // ...
    var leaved = false
    
    $('body').on('mouseover','li',function(){
        // ... I omited `setTimeout` to simplify the explanation
        leaved = false
        jQuery.ajax(
                {
                    // ...
                    success: function(data){
                        if (leaved) return;
                        $('#res').html(data);
    
                    }
                });
        // ...
    
    });
    $('body').on('mouseleave', 'li', function() {
        // ...
        leaved = true
    });