'How can I abort a javascript function if a second call to it is made?

How can I kill a Javascript function if it's still running when it gets called again?

Situation is this. I have an HTML5 Android app which has a search function. As the user types, it searches the HTML5 database for matches. Each keystroke in the search box fires off a function to get suggestions. But because the user can type faster than the database engine can return suggestions on relatively slow devices (like my own, or indeed the emulator) subsequent keypresses get queued up, so that it can take a while for the suggestions to match what the user's typed.

So what I'd like to do is to find some way of killing off a previous invocation of the getSuggestions function if it's invoked again before finishing.

Easy enough to set a global which the function tests at various stages and aborts if it sees it, but that won't stop queries piling up in the database engine, which I'm guessing is probably where the blockage is occurring. Which is why I'm looking for some way to kill off the whole function.



Solution 1:[1]

Sounds like you want underscore.js debounce method

Basically you would use it like this: (using jQuery for brevity)

$('#searchfield').keyup(_.debounce(getSuggestions, 250));

This will invoke the getSuggestions function only when the event hasn't fired for 250 ms. So if you are typing, nothing happens until you pause for at least a quarter second.

How it works is pasted below. It wraps a bunch of logic around a function and returns a new function. Isn't functional programming fun?

  // Returns a function, that, as long as it continues to be invoked, will not
  // be triggered. The function will be called after it stops being called for
  // N milliseconds. If `immediate` is passed, trigger the function on the
  // leading edge, instead of the trailing.
  _.debounce = function(func, wait, immediate) {
    var timeout, result;
    return function() {
      var context = this, args = arguments;
      var later = function() {
        timeout = null;
        if (!immediate) result = func.apply(context, args);
      };
      var callNow = immediate && !timeout;
      clearTimeout(timeout);
      timeout = setTimeout(later, wait);
      if (callNow) result = func.apply(context, args);
      return result;
    };
  };

Solution 2:[2]

Since JavaScript is single threaded, it won't be possible to interrupt a function execution. The browser will simply "freeze" until the function returns. In fact, you won't even be able to set a global variable.

So, what you need to do is to break up your search into little pieces (search 1% of the database at a time, for example). Make sure each piece takes no more than 100ms to execute on any device. Then keep calling the search function for the different pieces in the browser's event loop using SetTimeout(getSomeMoreSuggestions, 0) for example.

Then, you can check whether the user made a change to the edit box every time before you reschedule the next execution of the search (i.e. right before SetTimeout).

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2