Skip to content

Callback Functions in JS ft. Event Listeners

Episode 14 : Callback Functions in JS ft. Event Listeners

Section titled “Episode 14 : Callback Functions in JS ft. Event Listeners”
flowchart TD
Main["Main Thread
(Call Stack)"]
Main --> Sync["Synchronous Code
console.log('x')
function y()
etc."]
Main --> Async["Async Operation
setTimeout(cb, 5000)"]
Async --> WebAPI["Web API Environment
Timer starts counting 5s
Callback cb() stored"]
WebAPI -->|"After 5s"| CallbackQ["Callback Queue
cb() waiting..."]
Main -->|"After GEC pops"| EventLoop["Event Loop
Checks if Call Stack is empty"]
CallbackQ -->|"Stack empty? Push!"| EventLoop
EventLoop -->|"cb() runs"| CallStack["Call Stack
cb() executes"]
style Main fill:#7c3aed,color:#fff
style Sync fill:#4f46e5,color:#fff
style Async fill:#6366f1,color:#fff
style WebAPI fill:#059669,color:#fff
style CallbackQ fill:#d97706,color:#fff
style EventLoop fill:#dc2626,color:#fff
style CallStack fill:#7c3aed,color:#fff
  • Functions are first class citizens ie. take a function A and pass it to another function B. Here, A is a callback function. So basically I am giving access to function B to call function A. This callback function gives us the access to whole Asynchronous world in Synchronous world.
setTimeout(function () {
console.log("Timer");
}, 1000); // first argument is callback function and second is timer.
  • JS is a synchronous and single threaded language. But due to callbacks, we can do async things in JS.
setTimeout(function () {
console.log("timer");
}, 5000);
function x(y) {
console.log("x");
y();
}
x(function y() {
console.log("y");
});
// x y timer
  • In the call stack, first x and y are present. After code execution, they go away and stack is empty. Then after 5 seconds (from beginning) anonymous suddenly appear up in stack ie. setTimeout
  • All 3 functions are executed through call stack. If any operation blocks the call stack, its called blocking the main thread.
  • Say if x() takes 30 sec to run, then JS has to wait for it to finish as it has only 1 call stack/1 main thread. Never block main thread.
  • Always use async for functions that take time eg. setTimeout
// Another Example of callback
function printStr(str, cb) {
setTimeout(() => {
console.log(str);
cb();
}, Math.floor(Math.random() * 100) + 1);
}
function printAll() {
printStr("A", () => {
printStr("B", () => {
printStr("C", () => {});
});
});
}
printAll(); // A B C // in order
  • We will create a button in html and attach event to it.
index.html
<button id="clickMe">Click Me!</button>;
// in index.js
document.getElementById("clickMe").addEventListener("click", function xyz() {
//when event click occurs, this callback function (xyz) is called into callstack
console.log("Button clicked");
});
  • Lets implement a increment counter button.
    • Using global variable (not good as anyone can change it)
      let count = 0;
      document
      .getElementById("clickMe")
      .addEventListener("click", function xyz() {
      console.log("Button clicked", ++count);
      });
    • Use closures for data abstraction
      function attachEventList() {
      //creating new function for closure
      let count = 0;
      document
      .getElementById("clickMe")
      .addEventListener("click", function xyz() {
      console.log("Button clicked", ++count); //now callback function forms closure with outer scope(count)
      });
      }
      attachEventList();
      Event Listerner Demo

Garbage Collection and removeEventListeners

Section titled “Garbage Collection and removeEventListeners”
  • Event listeners are heavy as they form closures. So even when call stack is empty, EventListener won’t free up memory allocated to count as it doesn’t know when it may need count again. So we remove event listeners when we don’t need them (garbage collected) onClick, onHover, onScroll all in a page can slow it down heavily.

Watch Live On Youtube below:

Callback Functions in JS ft. Event Listeners in JS Youtube Link