尝试为jQuery AJAX请求添加延迟

8

我正在尝试延迟一个AJAX请求,使其在输入单元格的最后一个keyup之后2-3秒发送。
到目前为止,我已经成功地延迟了这些请求,但是在2-3秒后,每个字段的keyup都会发送一个请求...
我该如何让jQuery取消前面的请求,只发送最后一个keyup呢?
以下是到目前为止的代码:

$('#lastname').focus(function(){
          $('.terms :input').val(""); //clears other search fields
}).keyup(function(){
    caps(this); //another function that capitalizes the field
    $type = $(this).attr("id"); // just passing the type of desired search to the php file
        setTimeout(function(){ // setting the delay for each keypress
                ajaxSearchRequest($type); //runs the ajax request

        }, 1000);
});

上述代码将等待1秒钟,然后根据按键发送4-5个AJAX请求。 我只想在最后一个 keyup 后发送一个请求。
我在StackOverflow中找到了一些类似的解决方案,但由于我的编程知识有限,我无法将它们实现到我的项目中。

[已解决] 最终工作代码,感谢 @Dr.Molle:

$('#lastname').focus(function(){
          $('.terms :input').val("");
}).keyup(function(){
    caps(this);
    $type = $(this).attr("id");

    window.timer=setTimeout(function(){ // setting the delay for each keypress
            ajaxSearchRequest($type); //runs the ajax request

        }, 3000);

}).keydown(function(){clearTimeout(window.timer);});

这是 ajaxSearchRequest 的代码:

function ajaxSearchRequest($type){
                var ajaxRequest2;  // The variable that makes Ajax possible!

                try{
                  // Opera 8.0+, Firefox, Safari
                  ajaxRequest2 = new XMLHttpRequest();
                }catch (e){
                  // Internet Explorer Browsers
                  try{
                     ajaxRequest2 = new ActiveXObject("Msxml2.XMLHTTP");
                  }catch (e) {
                     try{
                    ajaxRequest2 = new ActiveXObject("Microsoft.XMLHTTP");
                     }catch (e){
                    // Something went wrong
                    alert("Browser error!");
                    return false;
                     }
                  }
                }

                ajaxRequest2.onreadystatechange = function(){
                  if(ajaxRequest2.readyState == 4){

                        $result = ajaxRequest2.responseText;
                        $('#resultcontainer').html($result);

                    }}


                var searchterm = document.getElementById($type).value;


                var queryString ="?searchterm=" + searchterm +"&type=" +$type;


                if(searchterm !== ""){

                ajaxRequest2.open("GET", "searchrequest.php" + 
                                 queryString, true);
                ajaxRequest2.send(null);
                }
        }

请发布ajaxSearchRequest代码。 - Imdad
@Imdad 为什么这是必要的?你已经可以看到每个键盘按下都会创建一个新的定时器而不取消之前的。 - Esailija
还有其他工作需要处理。只有当我知道这个函数是什么时,我才能告诉你。 - Imdad
有没有办法在.keydown上取消延迟事件? 这样,如果没有进一步的keydown,keyup事件实际上会发生? - krasatos
3
解决方案是在设置新的超时时简单地取消之前(.clearTimeout)的超时。然后,最后一个 keyup 超时就不会被取消。 - Esailija
好方法。我没有想到那个 +1。 - Imdad
3个回答

17

将超时时间存储在一个变量中,这样您就可以清除最近的超时:

clearTimeout(window.timer);
window.timer=setTimeout(function(){ // setting the delay for each keypress
                ajaxSearchRequest($type); //runs the ajax request

        }, 3000);

当你在不使用全局变量存储该值的情况下完成它时,我会给你一个+1。 - Alnitak
1
非常感谢,它起作用了,这是最终代码:$('#lastname').focus(function(){ $('.terms :input').val(""); }).keyup(function(){ caps(this); $type = $(this).attr("id"); window.timer=setTimeout(function(){ // 设置每次按键的延迟 ajaxSearchRequest($type); // 运行ajax请求 }, 3000); }).keydown(function(){clearTimeout(window.timer);}); - krasatos
4
别激动,这只是示例代码。解决方案很明显,不需要使用闭包。 - Erik Reppen

3
你所要做的是所谓的“去抖动”(debouncing)。
这里有一个由Ben Alman开发的jQuery插件可以实现此功能。 underscore.js也包含了这个功能。
真的没有必要对ajax请求系统进行任何修改。只需要确保在正确的时刻调用它即可。

-2

我喜欢Molle的回答,但我想进一步提高性能。

var ajaxRequest2;  // The variable that makes Ajax possible!
function getAjaxObject()
{
                try{
                  // Opera 8.0+, Firefox, Safari
                  ajaxRequest2 = new XMLHttpRequest();
                }catch (e){
                  // Internet Explorer Browsers
                  try{
                     ajaxRequest2 = new ActiveXObject("Msxml2.XMLHTTP");
                  }catch (e) {
                     try{
                    ajaxRequest2 = new ActiveXObject("Microsoft.XMLHTTP");
                     }catch (e){
                    // Something went wrong
                    alert("Browser error!");
                   // return false;
                     }
                  }
                }
  return ajaxRequest2;


 }
   getAjaxObject();

    function ajaxSearchRequest($type){



               if(typeof ajaxRequest2 =="undefined" || ajaxRequest2 == false)
                {
                  return;
                }
               ajaxRequest2.abort();

                ajaxRequest2.onreadystatechange = function(){
                  if(ajaxRequest2.readyState == 4){

                        $result = ajaxRequest2.responseText;
                        $('#resultcontainer').html($result);

                    }}


                var searchterm = document.getElementById($type).value;


                var queryString ="?searchterm=" + searchterm +"&type=" +$type;


                if(searchterm !== ""){

                ajaxRequest2.open("GET", "searchrequest.php" + 
                                 queryString, true);
                ajaxRequest2.send(null);
                }
        }

这个更改将中止正在进行的ajax请求并发送一个新的请求。当您:

输入 -> 等待4秒钟 -> 发送请求 -> 再次输入(未收到响应) -> 等待4秒钟 -> 另一个请求触发时,它非常有用。


因为这是一个不好的答案吗?中止请求并不能帮助 - 服务器(通常)会继续处理查询。正确的解决方法不是继续发送请求。 - Alnitak
但是,它减少了网络开销。并解决了如果您打字速度较慢可能会收到多个响应的问题。 - Imdad
3
不,不发送请求会“减少网络负荷”。取消 AJAX 请求只是停止最终答案到达回调函数。 - Alnitak
常识告诉我们,先不发送请求比发送请求然后中止它们具有更小的网络开销。 - Esailija
当然,不发送请求会减少开销。但是取消请求比不取消要好。我认为这也是常识。我建议@krasatos使用它,并让您知道它是否实际上提高了性能。我以前使用过这种技术,实际上看到了很大的改进! - Imdad
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接