我有一个textarea,人们输入一些文本(自然),我想这样做,以便偶尔发出一个AJAX请求,以获得有关textarea的内容的一些建议(如堆栈溢出的相关问题,但对于textarea,而不是文本输入)。问题是我无法在每个按键时执行AJAX请求(它没用,而且非常耗费资源),我不确定最有效的方法是什么(每X个字一次?每隔X秒?或其他什么?)。
这样做最好的方法是什么?
提前谢谢。
答案 0 :(得分:64)
您可以将keypress
事件处理程序与setTimeout
结合使用,以便在按键后发送Ajax请求一定时间,如果在计时器完成之前发生另一次按键,则取消并重新启动计时器。假设你有一个id为'myTextArea'的textarea和一个名为doAjaxStuff
的Ajax回调函数:
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 );
答案 1 :(得分:12)
您正在寻找的内容称为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>
&#13;
答案 2 :(得分:9)
另一种选择是使用名为bindWithDelay的小型jQuery插件。它使用与接受的答案相同的setTimeout技术,但透明地处理超时,因此您的代码更容易阅读。 source code可以在github上看到。
$("#myTextArea").bindWithDelay("keypress", doAjaxStuff, 1000)
答案 3 :(得分:3)
如果您使用的是lodash.js(或underscore.js),则可以使用debounce function。
示例(用于keyup的jQuery):
$('#myTextArea').keyup(_.debounce(function() {
alert('hello');
}, 500));
答案 4 :(得分:1)
我个人会使用setInterval
监视textarea的更改,并在检测到更改时仅执行AJAX回调。每一秒都应该快速而缓慢。
答案 5 :(得分:0)
如果您对jQuery解决方案感兴趣,jQuery Suggest是一个很好的实现。
每次都没有意义重新发明轮子。
答案 6 :(得分:0)
如果您在网站周围使用此功能并且不想跟踪所有setTimeout引用等,那么我将其打包到可用的插件here中。
该插件为普通的$ .ajax方法添加了一些选项,用于缓冲和取消之前的ajax调用。