Javascript 如果按下另一个键,则放弃挂起/运行按键功能

Javascript 如果按下另一个键,则放弃挂起/运行按键功能,javascript,jquery,input,Javascript,Jquery,Input,我有一个搜索框,隐藏列表中不包含输入文本的所有行 这个方法非常有效,直到列表变成10000行。一次按键就可以了,但是如果用户键入几个字母的单词,该函数将针对每个按键进行迭代 我想做的是,如果按下一个新键,就放弃以前执行的任何函数 功能非常简单,如下所示: $("#search").keyup(function(e) { goSearch(); }); function goSearch() { var searchString = $("#search").val

我有一个搜索框,隐藏列表中不包含输入文本的所有行

这个方法非常有效,直到列表变成10000行。一次按键就可以了,但是如果用户键入几个字母的单词,该函数将针对每个按键进行迭代

我想做的是,如果按下一个新键,就放弃以前执行的任何函数

功能非常简单,如下所示:

    $("#search").keyup(function(e) {
       goSearch();
    });

function goSearch()
{
var searchString = $("#search").val().toLowerCase();
$(".lplist").each(function(index, element) {
    var row = "#row-" + element.id.substr(5);
        if ($(element).text().toLowerCase().indexOf(searchString,0) != -1)
    $(row).show();
    else
    $(row).hide();
});
}

谢谢

引入一个计数器
var keypressCount
,该计数器由按键事件处理程序增加。在
goSearch()
的开头,将其值写入缓冲区。然后在每次运行
$(“.lplist”)。each()
您会询问当前的
按键计数是否与缓冲的按键计数相同;如果没有,你就回来。我建议您使用
for()
,因为
更容易中断大于
$。每个()

更新: 您必须确保有时间触发/接收新的按键事件,因此将$.each()的匿名函数包装在一个超时内


参考资料:

您不能直接使用。Javascript不是多线程的,因此函数将运行并阻止任何按键操作,直到完成为止

从用户体验的角度来看,这样做是可以容忍的,即不要在关键事件上立即触发函数,而是等待一小段时间,然后触发事件

当用户键入时,超时功能将持续设置和重置,因此不会调用gosearch函数,因此用户的键入不会中断

当用户暂停键入时,超时将倒计时到零并调用搜索函数,该函数将运行并阻止键入,直到完成为止。但这没关系(只要它在一秒钟左右内完成),因为用户当前可能没有尝试键入

您还可以按实际要求执行操作,方法是将gosearch函数拆分为块,其中每个函数调用:*读取到目前为止已处理的行数的计数器,然后再处理500行并递增计数器。*使用setTimeout调用另一个gosearch,该时间的值为零。这将向其他“线程”生成事件,并允许快速更改搜索词

var goSearchTimeout = null;
var linesSearched = 0;

function keySearch(e){
    if(goSearchTimeout != null){
        clearTimeout(goSearchTimeout);
        linesSearched = 0;
    }
    goSearchTimeout = setTimeout(goSearch, 500);
}

$("#search").keyup(keySearch);

function highLight(index, element) {

    if(index >= linesSearched){
        var row = "#row-" + element.id.substr(5);
        if ($(element).text().toLowerCase().indexOf(searchString,0) != -1){
        $(row).show();
    else{
        $(row).hide();
    }
    if(index > linesSearched + 500){
        linesSearched = index;
        goSearchTimeout = setTimeout(goSearch);
        return;
    }
}

function goSearch(){
    goSearchTimeout = null;
    var searchString = $("#search").val().toLowerCase();
    $(".lplist").each(highLight);
}

如果要像这样使用超时回调,我强烈建议将代码包装到jQuery小部件中,这样,您就可以使用对象上的变量来存储变量goSearchTimeout等,而不是让它们作为全局变量浮动。

您可以使用全局变量来保存搜索字符串,并在搜索字符串更改时停止执行

重要信息:您必须在每次迭代中设置超时,以便暂停函数执行并更新全局变量,因为JavaScript是单线程的

您的代码如下所示:

var searchString;

$("#search").keyup(function(e) {
    // Update search string
    searchString = $("#search").val().toLowerCase();

    // Get items to be searched
    var items = $(".lplist");

    // Start searching!
    goSearch(items, searchString, 0);
});

function goSearch(items, filter, iterator)
{
    // Exit if search changed
    if (searchString != filter) {
        return;
    }

    // Exit if there are no items left
    if (iterator >= items.length) {
        return;
    }

    // Main logic goes here
    var element = items[iterator];
    var row = "#row-" + element.id.substr(5);
    if ($(element).text().toLowerCase().indexOf(filter, 0) != -1)
        $(row).show();
    else
        $(row).hide();

    // Schedule next iteration in 5 ms (tune time for better performance)
    setTimeout(function() {
        goSearch(items, filter, iterator + 1);
    }, 5);
}

聪明的想法,但它不会工作,因为JavaScript是单线程的。调用
goSearch()
时,在退出之前不会执行任何其他操作。因此,
keypressCount
变量在
goSearch()
完成其执行之前不会更新,即使
keypress
事件发生在
goSearch()
执行期间。如果
keypressCount
是一个全局变量,它会更智能。如有必要,请仔细阅读范围。:)您可以从任何函数内部操作全局变量(在函数外部声明),即使在函数返回后,它也会保留其值。当然可以,但由于JavaScript是单线程的,所以在函数完成执行之前不会更新变量。这就是你的解决方案不起作用的原因。很好,我看到你注意到了这一点,并相应地更新了你的答案,:-)javascript是多线程的,这就是为什么你得到了一个事件系统不,不是,这就是为什么你不应该编写长时间运行的函数!我发现:顺便说一句,即使在多线程的环境中,所有GUI事件都倾向于通过一个上下文,实际上都是单线程的。这至少适用于Windows和Java Swing应用程序,在这些应用程序中,写得不好的应用程序可能会通过不快速返回GUI事件通知调用来阻止GUI响应。不要吝啬,请投票支持一些答案,至少是Danack的:-)