最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

settimeout - Javascript search delay and collect input from eventlistener - Stack Overflow

programmeradmin0浏览0评论

I have a simple input box. When I write something, I want it to be delayed. The problem I have is after the delay when writing characters very fast it calls the console.log multiple times.

What happened now

I type a and wait. Then I type b c d fast and wait. Then e f fast and wait. It catches up which I don't want. I want it to collect what I type, but not output it until the delay is done.

a
.
.
.
b c d
b c d
b c d
.
.
.
e f
e f

What I want to happen

a
.
.
.
b c d
.
.
.
e f

var searchtimer;

window.addEventListener("DOMContentLoaded", () => {
  document.querySelector("#search").addEventListener("input", (e) => {
    searchtimer = setTimeout(() => {
      console.log(e.target.value);
      clearTimeout(searchtimer);
    }, 1000);
  });
});
<input id="search" type="text">

I have a simple input box. When I write something, I want it to be delayed. The problem I have is after the delay when writing characters very fast it calls the console.log multiple times.

What happened now

I type a and wait. Then I type b c d fast and wait. Then e f fast and wait. It catches up which I don't want. I want it to collect what I type, but not output it until the delay is done.

a
.
.
.
b c d
b c d
b c d
.
.
.
e f
e f

What I want to happen

a
.
.
.
b c d
.
.
.
e f

var searchtimer;

window.addEventListener("DOMContentLoaded", () => {
  document.querySelector("#search").addEventListener("input", (e) => {
    searchtimer = setTimeout(() => {
      console.log(e.target.value);
      clearTimeout(searchtimer);
    }, 1000);
  });
});
<input id="search" type="text">

Share Improve this question edited Mar 8, 2021 at 12:58 Nguyễn Văn Phong 14.2k19 gold badges46 silver badges63 bronze badges asked Mar 8, 2021 at 12:41 Jens TörnellJens Törnell 24.8k46 gold badges130 silver badges223 bronze badges 5
  • 1 Check this out. – DontVoteMeDown Commented Mar 8, 2021 at 12:48
  • 1 @DontVoteMeDown Yes, OPs code starts a new timeout for every input event, but OP doesn't need "another timer to get the input end". – Andreas Commented Mar 8, 2021 at 12:50
  • 1 Clear the timeout before you create a new one and it should work as expected (clearing the timeout when the timeout already happended doesn't make that much sense...) – Andreas Commented Mar 8, 2021 at 12:50
  • @Andreas yeah you're right, its the same thing. – DontVoteMeDown Commented Mar 8, 2021 at 12:51
  • @Andreas Yes, that was it! – Jens Törnell Commented Mar 8, 2021 at 12:59
Add a ment  | 

2 Answers 2

Reset to default 7

Your expected behavior looks like debounce.

It seems to me that you should clearTimeout before creating the new one.

var searchtimer;
window.addEventListener("DOMContentLoaded", () => {
  document.querySelector("#search").addEventListener("input", (e) => {
    clearTimeout(searchtimer); // <--- The solution is here
    searchtimer = setTimeout(() => {
      console.log(e.target.value);
    }, 1000);
  });
});
<input id="search" type="text">


More detailed explanation:

  • It is basically a way for eliminating unwanted signals from an input. So if the defined duration hasn't passed, the previous action should be eliminated by clearTimeout(searchtimer);
  • Keynote: The operator keeps track of the most recent value.

Read post "throttleTime vs debounceTime in RxJS" to understand in detail.

Solution with step by step explanation

So you need to debounce.

The below code shows how a function is executed only when the time difference between 2 keystrokes is at least 2 seconds.

let count=0;

//If we call this directly from the HTML, the function will be 
// fired for every click, which hinders the performance
let myFunction =()=>{
  document.querySelector("#demo").innerHTML = "Hello World "+ ++count ;
}

//So we'll call this debouncing wrapper function from the HTML instead
let myFunc=letsDebounce(myFunction,2000);

//The wrapper calls setTimeout to execute its argument fn after
// the specified delay, but if the triggering event fires again
// before the setTimeout duration finishes, then the timer gets reset
// so the previous call is ignored
function letsDebounce(fn,d){
  let timer;
  return function(){
    clearTimeout(timer);
    timer=setTimeout(fn,d);
  }
}
<button onclick="myFunc()">Debounce</button>

<p id="demo"></p>

发布评论

评论列表(0)

  1. 暂无评论