Prags
Prags

Reputation: 5

javascript auto complete performance issue

I have a custom autocomplete using javascript which calls below keyup function which inturn invokes a webservice to get results. It generates results, but when i type fastly in the field the characters are getting entered one by one slowly refining result for each character , so the final feel on UI looks like its very slow.Is there any possible way to set a typing delay so the function ACCrequestSuggestions to invoke service will get called when these is a considerable pause by user while entering on the field. Or is there any other better way to handle this using a jvascript. Please help.

/**
* Handles keyup events.
*/
AutoSuggestControl.prototype.handleKeyUp = function (oEvent /*:Event*/) {
var iKeyCode = oEvent.keyCode;
//for backspace (8) and delete (46), shows suggestions without typeahead
if (iKeyCode == 8 || iKeyCode == 46) {
    ACCrequestSuggestions(this, false);

//make sure not to interfere with non-character keys
} else if (iKeyCode < 32 || (iKeyCode >= 33 && iKeyCode < 46) || (iKeyCode >= 112 && iKeyCode <= 123)) {
    //ignore
} else {
    //request suggestions from the suggestion provider with typeahead
ACCrequestSuggestions(this,true);
        }
};

/**
* Generate results and create the autocomplete drop down
*/

ACCrequestSuggestions = function (oAutoSuggestControl /*:AutoSuggestControl*/,
                    bTypeAhead /*:boolean*/) {

var aSuggestions = [];

// suggestions function will invoke service call to generate results based on input
aSuggestions = new Suggestions();

   //provide suggestions to the control by building div of results
oAutoSuggestControl.autosuggest(aSuggestions, bTypeAhead);
};

UPDATE :

I used settimeout as suggested , it works well. It feels faster as i type. My websetvice data is not static data set. The webservice does the searching based on the characters i enter. So i cant cache the data on client side. So not much i can do about.

var timeout; // scope global
if (timeout != "")
{
clearTimeout(timeout);
}
timeout = setTimeout(function(){
//Code to retrieve suggestions
},50);

Upvotes: 0

Views: 538

Answers (2)

MartinWebb
MartinWebb

Reputation: 2008

You have a lot of code running here, many functions being called all of which may run many lines of code.

The place to start is to add some logic and try to thread your code.

If at all possible first wait for 2-3 character entries before doing anything, as most words need at least 2-3 letters.

Second. use a setTimeout call to wrap the main function call that does all the work, this create a thread situation where the DOM/UI is now freed. But it may not solve the problem alone.

// tmr must have the scope to exist across all your methods

tmr = setTimeout(function(){ACCrequestSuggestions(this,true);},300)

As I have shown this will reset the tmr each time the a key is typed. That will stop all code from running until 300ms after the last key press.

You can add a check to see if a tmr is set before resetting it, which will make the autosuggest run every 300ms as they type.

// for the purpose of the example we need a reference to our scope so we can
// use it in the function call below;

var self = this;
if (tmr) return
var tmr = setTimeout(function(){ACCrequestSuggestions(self,true);},300)

You then need to set tmr to undefined, in your code when the auto-suggest completes, allowing a new tmr to be fired in your type catch event.

tmr=undefied;

I would also take a good look at all the code and look to speed the thing up, if the webservice is good, this can be made to look almost instant using the right kind of strategy.

Update: How to speed up your javascript!

So many times on Stack Overflow i see questions regarding slow code. In this example the OP is seeking to call a webservice as fast as the user types. From the outset that will not work well.

The basics are when the user types a character say "A" he calls the webserver and does some API search on his big data and fires back a load of data, or a small subset of it. Then when the user types "P" --> "AP" he does this all over again, even though he has the data already from his last call.

First off when your searching for stuff you need 2-3 letters to get something meaningful, so that is the first place to speed it up and reduce load. Search after 2-3, this also reduces the load when the server sends back all that data.

Secondly once you get back that data in this example we need never call the server again. The searching can be done very easily in javascript, as we have all the data for results from A---> onwards.

These techniques increase the performance of your apps/sites 10 fold and reduce the load to your server, not to mention the experience for your user and your boss!

Upvotes: 0

chm-software.com
chm-software.com

Reputation: 351

You can use setTimeout() to create the delay and call ACCrequestSuggestions only once after multiple keystrokes have been registered:

AutoSuggestControl.prototype.handleKeyUp = (function() {
   var timer;
   return function (oEvent) {
     var that = this;
     try {
       clearTimeout(timer); //stop timeout on key up if it's already running
     } catch(ignore) {}
     //call your code with a given delay
     timer = setTimeout(function() {

       /***your original code***/
       var iKeyCode = oEvent.keyCode;
       //for backspace (8) and delete (46), shows suggestions without typeahead
       if (iKeyCode == 8 || iKeyCode == 46) {
         ACCrequestSuggestions(that, false);
       //make sure not to interfere with non-character keys
       } else if (iKeyCode < 32 || (iKeyCode >= 33 && iKeyCode < 46) || (iKeyCode >= 112 && iKeyCode <= 123)) {
         //ignore
       } else {
         //request suggestions from the suggestion provider with typeahead
         ACCrequestSuggestions(that,true);
       }

     }, 300); //300 ms should be nice for performance and also for user experience
   }
})();

Please mark that this version only calls ACCrequestSuggestions with the last key pressed when multiple keys are hit in a distance smaller than 300ms. This may cause problems but normally there will be only one result shown to the user and this should of course be the one generated by the last key press.

Upvotes: 1

Related Questions