Exploring the flow of the debounce function and its logic, especially when it comes to the Event object - what is the source of the values for (...args

Currently, I am immersed in a Javascript course and grappling with the intricacies of the code snippet provided below. While I have a solid grasp on most aspects of it, I find myself struggling to follow and comprehend the logic flow within the code, especially concerning the event objects. It is crucial for me to clarify these concepts before proceeding further.

Interestingly, another individual has articulated a similar query here, but unfortunately, I am unable to derive any meaningful insights from the responses shared.

Here's the current extent of my comprehension:

When a key is pressed -> The debounce function is invoked (and executed) with parameters func and delay. In this scenario, the func parameter refers to the onInput function (which, as per my understanding, automatically receives an event object when the addEventListener is triggered).

However, the onInput function is encapsulated within the debounce function with func.apply(null, args);. This raises a perplexing question regarding the creation and propagation of event objects throughout the code execution when keys are pressed.

Subsequently, my primary query revolves around where or how does return (...args) in the debounce function obtain its spread parameters?

Doesn't the debounce function receive the event object instead of onInput in this instance? If that is the case, then how does onInput access the event object?

Below is the snippet in question:

const fetchData = async (searchTerm) => {
    const response = await axios.get('http://www.omdbapi.com/', {
        params: {
            apikey: '6459bge8',
            s: searchTerm
        }
    });

    console.log(response.data);
};

const input = document.querySelector('input');

const debounce = (func, delay) => {
    let timeoutId;

//What is the source of values for ...args?
    return (...args) => {
        console.log(args);
      
        if (timeoutId) {
            clearTimeout(timeoutId);
        }
        timeoutId = setTimeout(() => {
            func.apply(null, args);
        }, delay);
    };
};

const onInput = (evt) => {
    fetchData(evt.target.value);
  };
  
input.addEventListener('input', debounce(onInput, 500));

Furthermore, I am befuddled when I comment out the code inside the returned function like so:

const debounce = (func, delay) => {
    let timeoutId;
  
    return (...args) => {
        console.log(args);
      
        // if (timeoutId) {
        //     clearTimeout(timeoutId);
        // }
        // timeoutId = setTimeout(() => {
        //     func.apply(null, args);
        // }, delay);
    };
};

In such a scenario, the passed-in func never executes, yet the console displays InputEvents upon pressing a key, indicating that the args originate from elsewhere rather than being set by func.apply(null, args);?

Answer №1

A key point to grasp from your code is that the addEventListener() function does not directly call the debounce() function. The debounce() function is actually triggered when the addEventListener is added to the input element, not when the input event itself occurs. This is because invoking debounce() executes the function and passes its return value as the second argument to addEventListener(). Keeping this in mind, you can rewrite your function as follows:

const inputHandler = debounce(onInput, 500); // debounce returns a function
input.addEventListener('input', inputHandler); // the returned function is used in the addEventListener function

Therefore, the function produced by debounce() is what triggers on an input event (not the debounce function itself). The debounce function is executed when the addEventListener() method is invoked, which happens immediately upon encountering that line in the interpreter, not when an input occurs.

In this scenario, doesn't the debounce function receive the event object instead of onInput? How does onInput access the event object then?

In light of the explanation provided above, it is the returned function from debounce() that serves as the second argument for addEventListener(). Consequently, the returned function functions as the callback and receives the event object, which it can access through ...args. In the code snippet mentioned, this means that inputHanlder obtains the event object upon being invoked by JavaScript when an input event takes place. Thus, debounce() never actually receives the event argument; rather, it is the inner returned function that gains access to it.

Since the returned function (i.e., the inner function in your code sample) acquires the event object, it can retrieve it via args. Subsequently, the inner function proceeds to execute/call the onInput function with the event object using func.apply(null, args);.


In regard to your final example, the func function remains dormant as it is never called anywhere within the code. Although it is passed into your function, it does not get invoked or run (unlike the initial example where it is indeed utilized with .apply()). Nevertheless, the InputEvent continues to be logged since addEventListener() is the one triggering the callback upon the occurrence of an input event. Consequently, the inner function retains access to the event object.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing AngularJS, implement ng-form and ng-repeat to seamlessly handle input validation and submission actions

Angular 1.6.2 I am experimenting with iterating over elements of a collection inputted by the user, checking their validity, and enabling the submit action if validation passes. I have tried using ng-form for this purpose and have come up with two differ ...

Methods for validating React-Router navigation via history.push by utilizing Jest?

What is the best approach to unit test the following function that uses Jest to programmatically direct me to a specified page? function navigateToHome() { history.push('/home'); return { type: 'NAVIGATE_HOME', } } ...

How can I close the sidebar with a single tap anywhere outside of it?

Is there a way to hide the sidebar when clicking anywhere on the screen? Can I show text when hovering over an image instead of having it always visible? function openNav() { document.getElementById("mySidenav").style.width = "300px"; document.getE ...

Modifying Stroke color in HTML5 Canvas

I am attempting to create a unique visual effect by drawing a circle resembling a clock using canvas 2d context. The idea is to initially draw the circle in black starting at point p1, and then when I complete a full circle tour it should erase as the colo ...

What is the best way to modify .js source files while using AjaxControlToolkit?

Currently, I am tackling the source code for AjaxControlToolkit in the VS2008 version. There are specific modifications I need to implement in the core javascript files like MicrosoftAjaxWebForms.js, but unfortunately, I am unable to locate the original so ...

Angular and Three JS collaboration leads to misplacement of canvas rendering

Currently in the process of developing code for a website, I am attempting to integrate Three JS with Angular. After conducting some research, I have found that this combination is feasible and I have successfully merged these two libraries. However, I am ...

Enhance User Experience with Dynamic Scroll Page Transition

Hey everyone! I've been working on revamping a website and stumbled upon this fascinating page transition that I would love to replicate. However, I haven't been able to find a JQuery library that can achieve this effect. Does anyone have any i ...

A guide on updating label text using JavaScript or jQuery following a click on an HTML form

Seeking a solution to modify the text underneath a name form element on a squarespace.com website. This platform aids in website creation, but direct manipulation of the source code is not allowed. However, injecting JavaScript is permitted. I have identi ...

The value attribute in the HTML input tag being dynamically increased by JavaScript

Hi there, can someone help me figure out how to save changes to the value attribute of an HTML input tag that is being incremented by JavaScript? Currently, every time I click on a specific element, the input field should increase by one. The problem is th ...

Blending the foundation of canvas text and HTML element sharing

I am currently working on drawing text to an HTML canvas element and positioning an HTML button next to it using CSS styling and JavaScript. My goal is to have both the text and button share the same font and baseline alignment, but I am facing some challe ...

What are the steps for performing projection in TypeScript?

Looking to fill up the orders array, which consists of objects of type Order. The desired output is orders=[{id:1,qt:4},{id:2, qt:2},{id:3,qt:2}]. How can I achieve this using TypeScript? I am new to this language. export class Product { constructor(publ ...

Steps to implement jQuery after executing the command "npm install jquery"

Greetings! I recently utilized npm install jquery to add jQuery to my project. However, I noticed that it was downloaded into node_modules\jquery along with some unnecessary files. My goal is to only move node_modules\jquery\dist\jquer ...

proper integration of socket.io

I have been experimenting with socket io for my project to display online friends, and I have noticed an issue that seems strange to me. Every time the page is rerendered (whether due to a user changing their profile information or sending a friend request ...

What steps should I take to resolve the issue with this error message: Error: listen EADDRINUSE

How can I resolve the following issue? system: gulp npm windows issue: ... Oh no. Encountered error listen EADDRINUSE 127.0.0.1:35729 ... Error: listen EADDRINUSE 127.0.0.1:35729 at Object._errnoException (util.js:1021:11) at _exce ...

Can coveralls/codecov be utilized on a local machine?

As per Coveralls public documentation found at , it is stated that "Your code must be hosted on GitHub, BitBucket, or GitLab". Furthermore, the npm package called "coveralls" available at https://www.npmjs.com/package/coveralls mentions that "This script ...

The issue of an unsuccessful Ajax call arises in a WordPress plugin when utilizing wp_remote_get

Encountering difficulties with the wp_remote_get function in my Wordpress plugin. The objective is to invoke a method within my primary public class using ajax. However, every time I attempt to make the call with the wp_remote_get function, it fails. This ...

Eliminate repeated elements within a JSON dataset to create a consolidated array

Looking to extract unique data from the JSON object below in order to create a result json with a list of questions and their corresponding choices. Any assistance would be greatly appreciated. Thanks in advance..!! var data = [ { "category": "s ...

How to pass command line arguments into Chrome using WebDriverIO Selenium from the config.js file

Is there a way to add the disable-web-security flag for Chrome in order to conduct UI tests? How can I incorporate commands into the wdio.config file () to achieve this? capabilities: [{ browserName: 'chrome' }] ...

The server may provide different responses based on whether the user is accessing the

I'm attempting to retrieve a download link from a server with Cloudflare protection in place. While my browser successfully downloads the file when I send a request, using fetch() results in receiving an HTML page instead. Even after trying to repli ...

Angular: Issue encountered while attempting to differentiate an '[object Object]'. Arrays and iterables are the only permissible types for this operation

I encountered the following error message while attempting to retrieve updated data: Error trying to diff '[object Object]'. Only arrays and iterables are allowed Snippet of Get Code: allDatas allData(data) { this.allDatas = data } Up ...