When you’re building any type of web application, performance is your main concern, especially for sites that carry interactions. Listening to events like user typing input, scrolling, and resizing may cause the application to become unresponsive when it performs heavy computations or calls an API.
debounce
and throttle
are two techniques that can slow down these event handlers by limiting the function calls. In this article, we’ll learn how to debounce and throttle watchers and event handlers in a Vue application.
Table of contents
Create a debounce
function
Debouncing is a technique that can improve your application’s performance by waiting to trigger an event until a certain amount of time has passed; implementing the debounce
function allows a function to wait a set time before running again.
Before jumping into the code, let’s understand the idea behind debouncing. As an example, imagine that a user is typing in a text box, and as the user types, we’d like to fetch data from an API. If we call the API as many times as the user types on their keyboard, the application will create a huge number of network requests, leading to a decrease in performance.
Let’s assume you’d like to debounce a function, in our case, the search
function. We set the function to be executed after a certain time period, which is the estimated amount of time that the user leaves the keyboard before typing each new character. If the user is typing within this time frame, we postpone our function call to the next time interval. With this approach, we can reduce the number of function calls within intervals of typing:
Below is the code snippet for the debounce
function:
export function debounce(fn, wait){ let timer; return function(...args){ if(timer) { clearTimeout(timer); // clear any pre-existing timer } const context = this; // get the current context timer = setTimeout(()=>{ fn.apply(context, args); // call the function if time expires }, wait); } }
The debounce
function takes two arguments, the function to be debounced and the wait time in milliseconds. It returns a function and can be called later:
const debouncedFunction = debounce(function() { ... }, 300); console.log(typeof debouncedFunction); // `function` When the debounce function is triggered:
In the code above, we cancel any pre-existing timeout, and we schedule a new timeout based on the specified wait time. When the timeout expires, we call the callback function with arguments.
Create a throttle
function
While debounce
calls a function when a user has not carried out an event in a specific amount of time, throttle
calls a function at intervals of a specified time while the user is carrying out an event.
For example, if we debounce the search
function with a timer of 300 milliseconds, the function is only called if the user did not perform a search in 300 milliseconds. However, if we throttle the search function with 300 milliseconds, the function is called every 300 milliseconds as the user is typing.
Below is the code snippet for the throttle
function in our example:
export function throttle(fn, wait){ let throttled = false; return function(...args){ if(!throttled){ fn.apply(this,args); throttled = true; setTimeout(()=>{ throttled = false; }, wait); } } }
When the throttle
function is triggered, the throttled
variable is set to false
, and the supplied function is called with arguments.
After the function call, we set the throttled
variable to true
. If any event happens in this specified time, the function is not called until the throttle
variable is set to true
. setTimeout
takes the responsibility of assigning a variable to throttled
after the wait time has expired.
Debounce a watcher
Let’s create a simple component where our task is to call the Fetch API and log the value when the user types in a text box:
<template> <div id="app"> <input v-model="value" type="text" /> <p></p> </div> </template> <script> export default { data() { return { value: "", }; }, watch: { value(newValue, oldValue) { console.log("value changed: ", newValue, oldValue); // call fetch API to get results } } }; </script>
In the example above, each time the user types a value, it is logged to the console and the API is called. We can’t call the API so often without degrading the application’s performance. Therefore, we’ll debounce the activity above and call this debounced function inside a watcher. For this, we can use the debounce
function, which we created earlier.
Below is the code after debouncing:
<template> <div id="app"> <input v-model="value" type="text" /> <p></p> </div> </template> <script> import {debounce} from "./Utils.js"; export default { data() { return { value: "", }; }, created(){ this.debouncedFetch = debounce((newValue, oldValue)=>{ console.log("value changed: ", newValue, oldValue); // call fetch API to get results }, 1000); }, watch: { value(...args) { this.debouncedFetch(...args); } } }; </script>
In the code above, the user can log to the console or call the API if 1000 milliseconds has passed since the last typing activity.
We’ll implement debouncing on the watcher by creating an instance of debouncedFetch
, which calls the debounce
function with a callback and a wait time. This instance is created in the created()
Hook, then we invoke the debouncedFetch
with the right arguments inside the watcher.
Debounce an event handler
Debouncing the watcher and event handlers are similar. Let’s consider the same example where the user types into a text box. After typing, we’ll log to the console and call the Fetch API.
Below is the example before debouncing:
<template> <input v-on:input="onChange" type="text" /> </template> <script> export default { methods: { onChange(event) { console.log('changed value', event.target.value); // call fetch API to get results } } }; </script>
Now, we’ll debounce the onChange
event handler to limit the function calls when the user types.
Inside the created()
Hook, create an instance of the debounce
function by passing an event handler and a wait time by naming it onChangeDebounced
. Then, assign onChangeDebounced
to an @input
event handler:
<template> <input @input="onChangeDebounced" type="text" /> </template> <script> import {debounce} from './Utils.js'; export default { created() { this.onChangeDebounced = debounce(event => { console.log('changed value:', event.target.value); // call fetch API to get results }, 1000); }, }; </script>
Conclusion
In this tutorial, we learned about debouncing and throttling the watcher and event handlers in Vue. debounce
and throttle
are two powerful techniques for improving your application’s performance by limiting function calls to slow down event handlers.
Now that you understand how debounce
and throttle
work, give it a try in your own project. You should see immediate performance benefits. Leave a comment and let me know how it goes!
The post How to debounce and throttle in Vue appeared first on LogRocket Blog.
from LogRocket Blog https://ift.tt/WUd3gi2
Gain $200 in a week
via Read more