Node.js-Blog#02-Part-B: When in Node a JavaScript function is invoked; where does it place the new frame?

Node.js-Blog#02-Part-B: When in Node a JavaScript function is invoked; where does it place the new frame?

Pre-requisite: jahidularafat.hashnode.dev/nodejs-blog02-pa..

2. Call Stack

  • A call stack is many times referred to as "the stack". It stores data about procedures that are currently running in a given program.
  • the main reason for having one (a stack) is to keep track of the point to which each active subroutine should return control when it finishes executing.
  • It is a LIFO data structure.
  • they are important because they store procedures so that they can be executed in an organized fashion.

2.1 How event loop interact with call stack?

  • The event loop continuously checks the call stack to see if there's any function that needs to run.
  • While doing so, it adds any function call it finds to the call stack and executes each one in order.
  • You know the error stack trace you might be familiar with, in the debugger or in the browser console?

    The browser looks up the function names in the call stack to inform you which function originates the current call.

  • Lets draw the call stack for the below code
const bar = () => console.log('bar')
const baz = () => console.log('baz')
const foo = () => {
      console.log('foo')
      bar()
      baz()
    }
foo()

And the output is

foo
bar
baz

Drawing the call stack of the above code:


                                                    console.log('bar')                                              console.log('baz')
            console.log('foo')      bar()           bar()                       bar()                   baz()       baz()                   baz()
    foo()   foo()                   foo()           foo()                       foo()       foo()       foo()       foo()                   foo()       foo()       EMPTY
    -----   ------------------      ---------       ------------------          ------      ------      -------     ------------------      -----       -------     ------
    A       B                       C               D                           E           F           G           H                       I           J           K

The event loop on every iteration looks if there's something in the call stack, and executes it:

iteration           method to call
----------------------------------
1                       foo()
2                      console.log('foo')
3                      bar()
4                      console.log('bar')
5                      baz()
6                      console.log('baz')
****until the call stack is empty.

2.2 Queuing Function Execution

  • The use case of setTimeout(() => {}, 0) is to call a function, but execute it once every other function in the code has executed. Code Example:
const bar = () => console.log('bar')
const baz = () => console.log('baz')

const foo = () => {
            console.log('foo')
            setTimeout(bar, 0)
            baz()
}

foo()

And the output is

foo
baz
bar --> See, **bar** is executed at last, which executed before **baz** in the earlier example. But why?

The answer to this why?

  • When setTimeout() is called, the Browser or Node.js starts the timer. Once the timer expires, in this case immediately as we put 0 as the timeout, the callback function is put in the Message Queue.
  • The Message Queue is also where user-initiated events like click or keyboard events, or fetch responses are queued before your code has the opportunity to react to them. Or also DOM events like onLoad.
  • The loop gives priority to the call stack, and it first processes everything it finds in the call stack, and once there's nothing in there, it goes to pick up things in the message queue.