如果用户提交新搜索,会中断搜索的执行?



我有一个文本字段,当用户键入时,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 个字母搜索的方法。

这可能吗?我该怎么做?

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

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

使用去抖动

lodash的去抖动而不是自己从头开始写作。

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>

延迟请求,直到用户完成键入

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

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

最新更新