0

Here is the code which I tried:

// **Creating variables and functions**
let number_object = { num: 0 }

function doHomework(callback) {     //Starts doing the homework, supposed to finish after 5 seconds
    console.log("writing")

    setTimeout(() => {
        callback()
    }, 5000)
}

function Finished() {        //Called when 5 seconds are over
    console.log("Finished the homework")
}

function loop_(num_object) {  
    ++num_object.num;
    let i = 0;
    for (i = 0; i < 3000000000; ++i) { }
    console.log(`loop number ${num_object.num} over`)
}

// **Calling functions now**
doHomework(Finished)

let i = 0;
for (i = 0; i < 10000000000; ++i) { }  //This takes much more than 5 seconds
console.log(`This took more than 5 seconds, yet "finished" is not going to appear next`)

loop_(number_object)
loop_(number_object)
loop_(number_object)
loop_(number_object)
loop_(number_object)
loop_(number_object)
loop_(number_object)
loop_(number_object)
loop_(number_object)
loop_(number_object)

The output is:

writing
This took more than 5 seconds, yet "finished" is not going to appear next
loop number 1 over
loop number 2 over
loop number 3 over
loop number 4 over
loop number 5 over
loop number 6 over
loop number 7 over
loop number 8 over
loop number 9 over
loop number 10 over
Finished the homework

So I think the output suggests that, the code first queues all the functions in the call stack and then runs them. Which is why all the 10 functions are queued in the call stack, so only after they're done, "finished" appears

Swp_j
  • 1
  • 2
  • Does this answer your question? [Difference between microtask and macrotask within an event loop context](https://stackoverflow.com/questions/25915634/difference-between-microtask-and-macrotask-within-an-event-loop-context) – Seblor Nov 15 '20 at 11:57
  • Ty @Seblor I might have to go through for a while, because I haven't heard of microtasks and macrotasks. Will let you know – Swp_j Nov 15 '20 at 12:00
  • You can also read the documentation on Microtasks : https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide although the StackOverflow answers on the question I linked should cover your case. – Seblor Nov 15 '20 at 12:02
  • @Seblor meanwhile, I don't mean to be rude, but, can you tell what happens first? – Swp_j Nov 15 '20 at 12:17
  • Sorry I don't have much time but I will be able to write an answer later today if you don't understand what is going on – Seblor Nov 15 '20 at 12:22

2 Answers2

0

This is known as run-to-completion before entering the event loop again.

the code first queues all the functions in the call stack and then runs them. Which is why all the 10 functions are queued in the call stack

No, the 10 functions are not queued on the call stack. They are "queued" in the program code, if at all. Just your bazillion increment operations are not queued anywhere. They are encoded in the program, which is then run.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Okay, so before running, the code knows that "my first job is to finish the functions present in the code" and whatever is called back, will be done so, after the previous functions? – Swp_j Nov 15 '20 at 12:47
  • Yes. It's not even about functions specifically, just "finish this code", including e.g. your top-level `for` loop. – Bergi Nov 15 '20 at 13:41
0

It is important to remember that setTimeout does NOT call the function you passed to it. Instead it saves a pointer to the function that javascript will call later when the timeout expires.

In this sense javascript is no different from Java, C/C++, Pascal, Python etc. In all those languages if you save a function pointer to a linked/list or array that function will not be called until you call it later. The only difference is that APIs with callbacks are part of the standard library built-in into javascript. To be sure such APIs also exist in other languages especially when it comes to GUI programming.

In terms of the call stack, javascript generally behaves exactly the same as C/C++ but it does get weird when closures are involved. With closures javascript's call stack behaves like Lisp/Scheme or Haskell or Swift or Python.

The event loop

It is important to note that javascript is single threaded (some may claim otherwise - they are wrong). The interpreter is structured generally as follows:

// Pseudocode

script_to_execute = compile_scripts();
event_handlers = [];

do {
    scheduled_callbacks = execute(script_to_execute)

    for each (callback in scheduled_callbacks) {
        event_handlers.push(callback)
    }

    event = wait_for_async_events()

    for each (callback in event_handlers) {
        if (callback.event == event) {
            script_to_execute = callback.script
        }
    }

}
while (event_handlers.length > 0)

So basically your calls to setTimeout will add those functions to a list of event handlers. Your entire script is originally in script_to_execute. If you look at the program flow above it should be obvious that no event can get processed as long as your script is still executing. Therefore everything asynchronous in javascript including setTimeout, HTTP requests, DOM updates etc. will only happen after the last line of your script.

As you can also see all this has nothing to do with the call stack or scope. It's just timing - some things just happen in the future instead of now.

slebetman
  • 109,858
  • 19
  • 140
  • 171
  • C++ and Java have closures as well, really nothing special about the call stack for any of them. Haskell's call stack, on the other hand, is a very different beast, but more because of lazy evaluation with thunks than because of closures. – Bergi Nov 15 '20 at 13:43
  • "*javascript is single threaded (other claims are wrong)*" - [even in the browser, it's not](https://stackoverflow.com/q/2734025/1048572). But javascript *as a language* is neither "single-threaded" nor "multi-threaded". While ECMAScript doesn't specify any builtins for threads, it also doesn't preclude an implementation from implementing them, and there *are* runtimes that run javascript on multiple threads. – Bergi Nov 15 '20 at 13:51
  • @Bergi While ECMAScript does not specify the single threaded behavior WHATWG and W3C do when it comes to things like `setTimeout`, `fetch` etc. – slebetman Nov 15 '20 at 14:07
  • For `setTimeout`, `fetch` and other asynchronous things, they specify an event loop, yes. For things like web workers, `SharedArrayBuffer`s and atomics they specify a multi-threaded environment. – Bergi Nov 15 '20 at 14:24