In this example, I have a table with 2,000 records in it full of first name, last name, email, and a search field where I can search for whatever I want. Now, if I start typing really quickly, you can see that it starts lagging behind, and I'm able to make it feel a little bit janky, because it's trying to change it on every key press. One way to help with this is a technique called debouncing, meaning that it takes the event and lets the event fire over and over again, but then it only calls it about, over whatever milliseconds you set after that last even is fired, and I'll set it to 500 milliseconds.
I'm going to use the lodash library to debounce the changes of search term. Then, when the search term is done changing, I'm going to change it to...or I'm going to assign debounce term to search term. What this looks like is, scope watch app. SearchTerm, and new old, and then I'll take my app debounce term and assign it to the new value, or just app. SearchTerm. Then do a scope apply, since we're outside of Angular, at this point.
If I refresh now, it's going to be the exact same behavior as before, because I've not debounced it yet. If I type John, Bill, Frank, you can see the little bit of lag and it's changing every single time I type a character. To debounce this, I need to wrap this function with a paren, and then use the _.debounce, and then after the function, how many milliseconds I want it to wait after that final event is fired.
I'm going to say, "500 milliseconds or half a second." Once I refresh now, you can see that, as I type, it doesn't change, but then after 500 milliseconds, it applies that change. So we'll say, "John, Bill, Frank." You can see that I can actually type John, Bill, and Frank. I can type John and Bill without it making a change, and it waits for me to stop typing for it to apply that final change.
You can also set something up like another watcher on SearchTerm that's instead of debouncing, we'll just do the basic function with new old, and then I'm going to say, "The app info message is loading..." and then when we're done here the app info message is just cleared out, so that when I do it this way, and I'll refresh, you can see that as I type, it will say, "loading," and then once done applying, it will make that change.
It gives you that feedback that something is happening while I'm typing, even though it's basically just waiting for you to finish typing to apply those changes. One last note is on that first change. You'll see that loading message, if you don't want that to appear on the very first one, for some reason, if you just say, "If new value is the same as old value," we'll just return out of that watch, so when I refresh here, it's not going to show that loading, because the SearchTerm is just an empty string, and an empty string.
Then it will only show up when you start typing something else. It's also important to note that this technique works really well for things like mouse moves or other events that fire quite often, whether it's polling or whatever. If you want to make sure you don't load too much data every single time you move the mouse, or type a character, or things like that. If you're firing an event over, and over, and over quite a lot, look into the debounce technique.