【问题标题】:Disrupt execution of search if user submits a new search?如果用户提交新搜索,会中断搜索的执行吗?
【发布时间】:2019-12-25 10:57:55
【问题描述】:

我有一个文本字段,当用户键入时,AJAX 请求被发送到服务器以执行搜索并返回结果:

<input type="text" class="form-control player-list-control-text" id="name" name="name" autocomplete="off" />

$('.player-list-control-text').keyup(function(){
    get_player_list();
});

function get_player_list(){
    $.ajax({
        url: '/player/list/get',
        data: {
            'club_id' : $('#club_id').val(),
            'position_id' : $('#position_id').val(),
            'name' : $('#name').val(),
            'page' : players_page,
            'sort_by' : sort_by,
            'sort_order' : sort_order,
        },
        type: 'POST',
        success: function(result) {
            if(result.hasOwnProperty('error'))
                show_msg('error', result.error);
            else
                load_players(result);
        },
        error: function (response) {
            handle_error(response);
        }
    });
}

问题是,搜索需要一两秒的时间来执行,所以当用户快速输入,比如 5 个字符时,请求会变得混乱,要么需要很长时间,要么显示错误的结果 -例如,4 字母搜索的结果而不是 5 字母搜索的结果。

我可以通过在客户端上保存请求时间或阻止用户在处理前一个请求时输入来确保显示最后一个请求的结果,但两者似乎都是不好的解决方案 - 第一个是因为它没有'实际上并没有为服务器节省任何麻烦,第二个是糟糕的用户体验。

我真正在寻找的是一种方法,可以在客户端发送新的 5 字母搜索查询时中断服务器上过时的 4 字母搜索中间执行。

这可能吗?我该怎么办?

后端脚本包含多个查询,因为我们必须搜索多个表(如果它们完全相关)。

编辑:关于引发密切投票的类似问题,解决方案不是我所追求的。我想中断服务器端处理,而不仅仅是停止客户端上的请求。

【问题讨论】:

标签: javascript php laravel


【解决方案1】:

使用debounce

lodash's debounce 而不是自己从头开始编写。

const debouncedGetPlayerList = _.debounce(get_player_list, 2000);

$('.player-list-control-text').keyup(function(){
    debouncedGetPlayerList(); // execute get_player_list after 2s non-interupted
});

现场示例:https://codepen.io/dcorb/pen/mVGVOL

$(document).ready(function(){

  var $statusKey = $('.status-key');
  var $statusAjax = $('.status-ajax');
  var intervalId;
  
  // Fake ajax request. Just for demo
  function make_ajax_request(e){
      var that = this;
      $statusAjax.html('That\'s enough waiting. Making now the ajax request');
     
      intervalId = setTimeout(function(){
         $statusKey.html('Type here. I will detect when you stop typing');
         $statusAjax.html('');
         $(that).val(''); // empty field
      },2000);
    }
  
  // Event handlers to show information when events are being emitted
    $('.autocomplete')
      .on('keydown', function (){  
      
        $statusKey.html('Waiting for more keystrokes... ');
      clearInterval(intervalId);             
      })
     
  
  // Display when the ajax request will happen (after user stops typing)
    // Exagerated value of 1.2 seconds for demo purposes, but in a real example would be better from 50ms to 200ms
  $('.autocomplete').on('keydown',
       _.debounce(make_ajax_request, 1300));
  });
body {
   background: #444444;
   color: white;
   font: 15px/1.51 system, -apple-system, ".SFNSText-Regular", "San Francisco", "Roboto", "Segoe UI", "Helvetica Neue", "Lucida Grande", sans-serif;
   margin:0 auto;
   max-width:800px;
   padding:20px;
}

form {
  display: inline-block;
  padding: 0;
  margin: 0;
  padding: 5px;
  margin: 5px 0 0 0;
}

input {
  padding:8px 20px;
  border-radius: 2px;
  border:0;
  font-size:20px;
}
.status-key,
.status-ajax {
  margin:10px 0;
}
.status-ajax {
  color:#99FF7E;
}
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>


<form>
  <div class="status-key">Type here. I will detect when you stop typing</div>
  <input type="text" class="autocomplete">
  <div class="status-ajax"></div>
</form>

【讨论】:

  • 它完全按照我下面的建议(在这种情况下),而无需加载另一个库。
【解决方案2】:

延迟请求直到用户完成输入

var timer;
$('.player-list-control-text').keyup(function(){
    clearTimeout(timer);
    timer = setTimeout(function () {get_player_list();}, 500);
});

500ms 为您节省了很多无用的搜索输入请求。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-01
    • 2022-08-24
    • 1970-01-01
    • 1970-01-01
    • 2010-11-26
    • 2015-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多