I'm facing an issue with a JavaScript event where an AJAX request is sent multiple times when the event is triggered rapidly. Let's say I have an input field that triggers an AJAX request on the "change" event. However, if I quickly type the word "phone" in the input field, the AJAX request is sent five times instead of just once. I want to introduce a delay and ensure that if a new change event is fired within that delay, the previous process is canceled and only the latest request is sent.
Here's the code snippet I've been working on:
$(document).on("input", "#product_search", function (e) {
let debounceTimer;
clearTimeout(debounceTimer);
debounceTimer = setTimeout(function () {
let inputValue = e.target.value;
$.ajax({
url: "pages/get_all_products.php",
method: "POST",
data: {
search: inputValue,
},
beforeSend: function () {
console.log("sending");
},
success: function (response) {
// Process the response
},
error: function () {
console.log("error");
},
complete: function () {
console.log("completed");
},
});
}, 100);
});
Unfortunately, this code doesn't solve the issue, as the AJAX request is still being triggered multiple times when typing quickly. I would greatly appreciate any guidance on how to implement a proper debounce functionality for this scenario. I expect it to send single request if I type fast enough.
I have already attempted to use the debounceTimer variable to clearTimeout() and reset the timer, but it doesn't seem to be working as expected.
Could someone please help me understand how to correctly debounce the event, so that only the latest AJAX request is sent even if the event is triggered multiple times within a short time frame?
It seems the variable declaration let debounceTimer
should be outside of the oninput
handler.
Otherwise, the variable is declared each time the event fires, it does not persist outside of the handler function, and its associated timer cannot be cleared by subsequent events. This is because a variable declared by let
is "limited to the scope of a block statement, or expression on which it is used" (let
@ MDN).
You may also want to increase the debounce time, depending on how fast you expect users to type.
let debounceTimer;
$(document).on("input", "#product_search", function(e) {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(function() {
console.log('Go!');
}, 300);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="product_search">