JQueryUI自动完成如何处理异步结果?

时间:2012-01-05 19:31:42

标签: javascript jquery jquery-ui asynchronous autocomplete

我无法理解JQueryUI的自动完成功能如何处理重复的按键导致异步结果。我需要具有类似功能的东西,但我不能让自动完成的结果正确进入。一个例子:

$(document).ready(function() {
    $('#textinput').live('keyup', function() {
        $.get('bacon.php', function(data) {
             $('#holder').html(data);
        });
    });
});

问题是如果快速输入,结果通常不会以正确的顺序返回。如果我输入“KEY”这个词,我可能会得到“K”,然后是“KEY”,然后是“KE”的结果,弄乱了#holder的内容。我注意到JQueryUI自动完成没有这个问题,但我无法理解它是如何处理它的。

3 个答案:

答案 0 :(得分:8)

关于这个特定问题,我没有看过jQuery的自动完成功能,但是我对自定义自动完成脚本的处理方法是,如果在某个时间范围内点击了另一个按键,我就会中止XHR请求。像这样:

 var xhr, throttle;

 $('.autocomplete').keyup(function() {
      var $this = $(this);
      if (throttle)
         clearTimeout(throttle); // Clear the previous request
      xhr.abort(); // Abort the last XHR request
      throttle = setTimeout( function() {
          xhr = $.getJSON('autocomplete.php', { data: $this.val() }, function(data) {
              // do something with response
          });
      }, 250); // wait 250 milliseconds before running this
 });

基本上,节流器确保我们在发送请求之前等待250毫秒,以防用户仍在键入(您可以将其设置为任何内容)。 “xhr”变量将XMLHttpRequest保存在变量中,如果我们得到另一个按键并且响应还没有回来,那么我们中止前一个,确保只有最新的一个实际返回响应。 / p>

希望有所帮助。

祝你好运:)

答案 1 :(得分:0)

我只是在做一些非常相关的事情。一个简单的“延迟”API,用于将函数转换为延迟委托。

Function.prototype.delayed = function(ms, reset)
{
    var timeout;
    var fn = this;
    return function()
    {
        var args = arguments;
        var scope = this;
        if (reset && timeout) clearTimeout(timeout);
        timeout = setTimeout(function() { fn.apply(scope, args) }, ms);
    };
};

请参阅fiddle了解样本。

在你的情况下,它就像这样

$(document).ready(function() {
    $('#textinput').live('keyup', (function() {
        $.get('bacon.php', function(data) {
            $('#holder').html(data);
        });
    }).delayed(300, true));
});

答案 2 :(得分:0)

遇到完全相同的问题,偶然发现了Addy Osmani提到的proxy pattern

我认为它与实时观察者事件更相关

$( "button" ).on( "click", function () {
    setTimeout( $.proxy( function () {
        // "this" now refers to our element as we wanted
        $( this ).addClass( "active" );
    }, this), 500);
});

希望有所帮助