异步搜索事件处理

Async search event handling

本文关键字:事件处理 搜索 异步      更新时间:2023-09-26

我有一个基于web的搜索输入。在每个onkeyup事件中,都会从带有JavaScript的客户端向返回搜索响应的PHP文档发出异步请求,然后JS获取搜索响应并将其写入客户端。这部分工作正常。

然而,我的问题是,当用户键入搜索词的速度超过系统的响应速度时。

假设一个快速输入的用户正在搜索单词super。用户键入s(并且对s进行搜索),当对s执行和写入搜索时,用户键入u,并且现在对su的搜索被排队。然后,这个打字非常快的用户键入一个p,而对s的初始搜索正在完成,现在对susup的搜索正在排队。

如果用户键入速度较慢,就没有问题,而且我的搜索工具可以响应每个按键,而无需排队搜索请求。但是,如果用户键入的速度非常快,那么在完成键入搜索词后,他们将看到几次搜索结果刷新在他们之前闪烁,因为脚本正在完成队列中的项目。

如何改进我的代码以改善用户体验?

例如,您将如何编写脚本,以便丢弃除最后一个队列项目之外的任何队列项目?

您可以通过一次超时(称为去抖动)来完成此操作:

"去抖动意味着将几个时间上接近的信号合并为一个信号。"

var timer;
function keyup() {
  clearTimeout(timer);
  timer = setTimeout(function() {
    search(this.value);
    timer = null;
  }, timer ? 50 : 1);
}

这段代码意味着,如果用户输入太快(在这种情况下是delta<50ms),操作将不会排队,但最新的操作总是覆盖以前的操作。

还有另一种方法(称为节流):

"节流是重复事件发生率的降低。"

var timer;
function keyup() {
  if (!timer)
    timer = setTimeout(function() {
      search(this.value);
      timer = null;
    }, 100);
  }
}

最后,您可以一次获取更多数据来解决延迟问题
请参阅这篇文章,了解Flickr是如何做到的:构建快速客户端搜索

还要确保根据数据更改的频率使用某种缓存(APC/memcache)。这可以大大减轻数据库的压力。

我认为最好的解决方案是为"onkeyup"设置计时器。

带有jQuery的示例:

var timer = null;
$('input').keyup(function(){
    if(timer!=null){
        clearTimeout(timer);
    }
    // wait and call in 150 ms
    timer = setTimeout(function() {
        // call here your search function!
        ....
    }, 150);
});

正如一些人所提到的,您可以使用超时来减缓从服务器获取结果的速度。不过,请注意,这仍然会为用户显示一个小延迟。

如果数据是在页面加载时提取和存储的候选数据,那么只需从客户端内存中检索数据,就可以提供更快的自动完成解决方案。