Hey guys whilst I was trying to solve this issue I came across your thread which I found helpful to an extent, basically I spent hours reading up and realised that the solutions you provided doesn't do what you actually wanted it to do so here I offer my solution.

In a new thread to be clear and this is my first post so, please read ;)

The answers you give don't actually clear the timer since it is in the function after the one you have just executed let me explain...

function doSomething() {
        if(timeout) clearTimeout(timeout);
        var timeout = setTimeout(function() {
        // your function code
}, 2000);
}

When you call doSomething() twice the second call is queued and isn't executed till the entire function as finished so therefore the clearTimeout call is pointless since the entire first call as already been executed... this included the time-out you have set.

So time for my solution, is if this is for a user input field is quite simple and cheeky.

Retrieve the length of the input box outside of the timeout and then also inside and check they are the same length. This isn;t a brilliantly slimline solution as it technically executes the "function" but as you can see it executes 2 or 3 lines of it ;), and strips the bulk of your code.

function doSomething() {

        var outside = getElementById("inputid").value;

        var timeout = setTimeout(function() {
        var inside = getElementById("inputid").value;
        if(inside.length != outside.length) {return}

        // if lengths have changed during the time out period the function stops....the                                    next one executes but again stops after 4 lines if the user continues to type, if they have stopped you will continue to....
        
       // your function code
}, 2000);
}

I hope this gets read and some of you veteran coders give your opinions or point out any problems with this code.

Dani AI

Generated

Good points from about the timer being effectively re-created on each call, and useful follow-ups from and about where to store state. A more robust pattern is a debounced wrapper that keeps the timer in a closure (so it isn’t re-declared on every call), preserves this and arguments, and exposes a cancel method for cleanup. This avoids brittle heuristics like comparing lengths and makes the behavior reusable.

function debounce(fn, delay, opts) {
  let id = null;
  const immediate = !!(opts && opts.immediate);
  function wrapped(...args) {
    const ctx = this;
    const callNow = immediate && !id;
    clearTimeout(id);
    id = setTimeout(() => {
      id = null;
      if (!immediate) fn.apply(ctx, args);
    }, delay);
    if (callNow) fn.apply(ctx, args);
  }
  wrapped.cancel = () => { clearTimeout(id); id = null; };
  return wrapped;
}

Usage example (attach to an input handler; call cancel when tearing down):

const search = debounce(function(term) {
  // perform AJAX/search with `term`
}, 400);

inputElement.addEventListener('input', e => search(e.target.value));
// later, on form submit or unload: search.cancel();

Troubleshooting notes: checking string length (as in earlier posts) misses same-length edits (paste/replace). Storing the timer as a function property (as suggested) works, but closures keep state local and avoid polluting globals. Consider whether debounce or throttle fits the use case (debounce waits for "quiet"; throttle limits rate). Always call the cancel method when removing listeners or when a pending action must be aborted.

Recommended Answers

All 3 Replies

The first function gives you more flexibility and ease in calling and passing variables. The second is an inline which has more control but at the same time is more difficult to construct especially when you need to pass in variables. It is good to use the call as a function pointer.

In your code, it contains hard-coded (get id and get value) which may not be flexible enough. Yet, you could modify it to use in something else.

However, your "timeout" will become useless because it is declared inside the doSomething() scope. If you want to keep the value to be clear later, you need to save it somewhere. Global variable may be used in this case though.

So, it depends on how you construct your script. I normally check for duplicated calls inside the function being called itself because I need to do a lot of things in a function when I keep calling it. :P

Taywin,

Your normally superb posts hit a speed bump. "If you want to keep the value ..." perhaps you should attach it as a property to the function, no?

function maybe_later() {
    
    if ( maybe_later.timeout ) { ... }

    maybe_later.timeout = setTimeout( ... );

Ah yes, you are correctly. Make it global to its own function. Thanks for reminding me. :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.