我有一个文本区域,人们在其中输入一些文本(自然地),并且我想让它不时发出 AJAX 请求,以获取有关文本区域内容的一些建议(如堆栈溢出的相关问题,但对于textarea,而不是文本输入)。问题是我不能在每次按键时都执行 AJAX 请求(这将是无用的并且非常消耗资源),而且我不确定最有效的方法是什么(每 X 字?每 X 秒) ? 或者是其他东西?)。
这样做的最佳方法是什么?
先感谢您。
我有一个文本区域,人们在其中输入一些文本(自然地),并且我想让它不时发出 AJAX 请求,以获取有关文本区域内容的一些建议(如堆栈溢出的相关问题,但对于textarea,而不是文本输入)。问题是我不能在每次按键时都执行 AJAX 请求(这将是无用的并且非常消耗资源),而且我不确定最有效的方法是什么(每 X 字?每 X 秒) ? 或者是其他东西?)。
这样做的最佳方法是什么?
先感谢您。
您可以将keypress事件处理程序与事件处理程序结合使用,setTimeout以便您在按键后的设定时间发送 Ajax 请求,如果在计时器完成之前发生另一次按键,则取消并重新启动计时器。假设您有一个 ID 为“myTextArea”的 textarea 和一个名为 的 Ajax 回调函数doAjaxStuff:
function addTextAreaCallback(textArea, callback, delay) {
var timer = null;
textArea.onkeypress = function() {
if (timer) {
window.clearTimeout(timer);
}
timer = window.setTimeout( function() {
timer = null;
callback();
}, delay );
};
textArea = null;
}
addTextAreaCallback( document.getElementById("myTextArea"), doAjaxStuff, 1000 );
您要查找的内容称为debouncing. 这是原生 JavaScript 中的通用算法:
function debounce(fn, duration) {
var timer;
return function() {
clearTimeout(timer);
timer = setTimeout(fn, duration)
}
}
这是如何将它与onkeyup事件一起使用的示例:
function debounce(fn, duration) {
var timer;
return function(){
clearTimeout(timer);
timer = setTimeout(fn, duration);
}
}
const txt = document.querySelector('#txt')
const out = document.querySelector('#out')
const status = document.querySelector('#status')
const onReady = () => {
txt.addEventListener('keydown', () => {
out.classList.remove('idle')
out.classList.add('typing')
status.textContent = 'typing...'
})
txt.addEventListener('keyup', debounce(() => {
out.classList.remove('typing')
out.classList.add('idle')
status.textContent = 'idle...'
}, 800))
}
document.addEventListener('DOMContentLoaded', onReady)
#wrapper{
width: 300px;
}
input{
padding: 8px;
font-size: 16px;
width: 100%;
box-sizing: border-box;
}
#out{
margin: 10px 0;
padding: 8px;
width: 100%;
box-sizing: border-box;
}
.typing{
background: #A00;
color: #FFF;
}
.idle{
background: #0A0;
color: #FFF;
}
<div id="wrapper">
<input id="txt" placeholder="Type here" />
<div id="out">Status: <span id="status">waiting...</span></div>
</div>
另一种选择是使用一个名为bindWithDelay的小型 jQuery 插件。它使用与接受的答案相同的 setTimeout 技术,但透明地处理超时,因此您的代码更容易阅读。该源代码可以看出在github。
$("#myTextArea").bindWithDelay("keypress", doAjaxStuff, 1000)
如果您使用 lodash.js(或 underscore.js),您可以使用 debounce函数。
示例(用于 keyup 的 jQuery):
$('#myTextArea').keyup(_.debounce(function() {
alert('hello');
}, 500));
如果您对 jQuery 解决方案感兴趣,jQuery Suggest是一个很好的实现。
每次都重新发明轮子是没有意义的。