减少即时搜索中的ajax调用次数

时间:2016-03-21 11:13:33

标签: javascript jquery ajax

我正在尝试为我的网站进行即时搜索。一切正常,除此之外。

var timeOut;
$('#search input[name=\'search\']').on('keyup', function(e) {
    // If enter - submit the search field
    if (e.keyCode == 13) {
        $('header input[name=\'search\']').parent().find('button').trigger('click');
    }
    // Call only when length is at least 2 and the key pressed is alphanumeric
    else if ($('#search input[name=\'search\']').val().length>2 && ((e.keyCode>=65 && e.keyCode<=90) || (e.keyCode>=97 && e.keyCode<=122))) {
        timeOut = null;
        //alert(timeOut);

        if (!timeOut) {
            timeOut = setTimeout(function() {
                $.ajax({
                    url: 'ajax.php',
                    type: 'post',
                    async: false,
                    data:  'ACTION=SEARCH&search='+$('#search input[name=\'search\']').val(),
                    dataType: 'json',
                    beforeSend: function() {
                        $('#loader-icon').show();
                    },
                    complete: function() {
                        $('#loader-icon').hide();
                    },
                    success: function(json) {
                        //$('.product-list-row').html(json);
                        $('#search-listing').html(json['html']);
                    },
                    error: function(xhr, ajaxOptions, thrownError) {
                        alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
                    }
                });
                timeOut = null;
            }, 500);
        }
    }
});

问题1:我的脚本最终会向服务器发出太多调用,由于某些原因setTimeOut没有像我预期的那样工作。只有当用户完成打字或类似的操作时才应该进行Ajax调用,而不是在每次按键时都进行。

问题2:出于某种原因,当我快速输入时,输入条不会被编辑。然而,ajax可以工作,但最后一个文本输入。

2 个答案:

答案 0 :(得分:2)

您可以使用AJAX返回的 jqXHR 对象中止之前的调用,而不是尝试使用setTimeout解决此问题。使用它更干净,更简单。同时删除async: false,

var timeOut;
var xhr;
$('#search input[name=\'search\']').on('keyup', function(e) {
    // If enter - submit the search field
    if (e.keyCode == 13) {
        $('header input[name=\'search\']').parent().find('button').trigger('click');
    }
    // Call only when length is at least 2 and the key pressed is alphanumeric
    else if ($('#search input[name=\'search\']').val().length>2 && ((e.keyCode>=65 && e.keyCode<=90) || (e.keyCode>=97 && e.keyCode<=122))) {
        if(xhr && xhr.readyState != 4){
            xhr.abort();
        }   
        xhr = $.ajax({
            url: 'ajax.php',
            type: 'post',
            data:  'ACTION=SEARCH&search='+$('#search input[name=\'search\']').val(),
            dataType: 'json',
            beforeSend: function() {
                $('#loader-icon').show();
            },
            complete: function() {
                $('#loader-icon').hide();
            },
            success: function(json) {
                //$('.product-list-row').html(json);
                $('#search-listing').html(json['html']);
            },
            error: function(xhr, ajaxOptions, thrownError) {
                alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
            }
        });
    }
});

答案 1 :(得分:1)

正确的解决方案是两者的结合,中止运行请求,如果应该进行新的请求,还要解决新请求的触发问题。您可以使用下划线库,它具有很好的功能,称为 debounce (请参阅http://underscorejs.org/#debounce),您的代码应如下所示:

// This is your xhr, each request save into this 
// variable, in order to be able to abort it if needed
var xhr;

// Wrap your event handler using the debounce function
$("#search").on("keyup", _.debounce(function(e) {
   // Abort running request
   if(xhr) {
    xhr.abort();
    xhr = null;
  }

  // Store the new request
  xhr = $.ajax({
   // Search for the term $(this).val()
  });
},500));

无需触发每个键盘的搜索,但只有当用户停止键入时 - debounce才能为您完成。如果要求提出请求,则无需处理以前的结果。