Skip to main content

Asynchronous JS & Promises

Screenshot 2023-08-12 at 03.51.07.jpg

Js is:

synchronous language = a line is finished before moving on to the next one.

single threaded = one command at a time

but how to handle long lasting functions, like getting data from a server?

Screenshot 2023-08-12 at 04.07.49.jpg

Screenshot 2023-08-12 at 04.40.04.jpg

JS and browser features are different. But we can use them inside our JS code. These look like JS functions, we can run them from inside our code but they do not belong to JS.

This means a big part of what we are doing in JS is not even JS at all!

Callback Queue & Event Loop

Callback Queue ⇒

Screenshot 2023-08-13 at 18.37.36.jpg

Timer is a web feature. The timer is started on browser api, when timer ends the callback func. is added to the JS callback queue.

In this function, after 0ms (instant), the callback function is sent to the callback queue, ready to run.

For something to get out of callback queue to call stack. There is a #1 rule:

The global execution context must be finished. Meaning any synchronous code must have finished running.

All regular code must be finished before we grab anything from the queue.

How does JS implement this?

Event Loop ⇒ Checks before every line if the call stack is empty. If there is anything in the queue. If there is still global code to run, it will not even check the queue. If it is, it grabs from queue to add to the stack. Constantly does this check.

This approach here with callback, creates Callback Hell. Which is having a chain of callbacks, since they can only access the data acquired from background operations. And error handling becomes hard. This is solved by promises.

Promises

This is a way to ensure that, when a background operation is started it doesn’t just disappear from JS memory to somewhere else (in browser apis, like DOM or Timer etc). These operations can now have a reference is JS memory. So the we have consistency between things in background and in JS.

For example Web’s xhr/fetch API. When you send a network request to be executed by browser, now it’s going to have a consequence in JS memory as well. It’ll return a Promise object that’ll set in memory. It’ll be filled with state information and returned data from the request run in browser.

ES6+ Promises

Screenshot 2023-08-13 at 19.03.59.jpg

The value in the promise object created in JS memory is filled, when the fetch is finished.

But how can I figure out when the value is available and we want to use it immediately?

The onFulfilled property in the promise object, array, will be filled with functions that will run with the data received when the promise is finished.

.then() adds the function given to the onFulfilled array

My personal question here was: SInce it is not JS engine (ECMAcore) that is handling console.logs, it is a webAPI. Why doesnt console.logs get into callback queue like other functions. Well because it has no callback like setTimeout or fetch. It is a synchronous operation although it is leaving the JS engine. Well there is no callback is the good answer probably. JS engine fires it off and there it goes. nothing (data) will be coming back to be run in a function.

MicroTask Queue

another queue similar to callback queue. Any function attached to a promise using ‘then’ method, and then triggered through JS joins here.

(anything of a normal callback call (like from setTimeout, triggered from outside) joins the callback queue)

When event loop goes ahead and checks all the code, decides all sync code has finished running. It checks the microtask queue first to take tasks to call stack.

error catching ⇒ either second argument or by .catch()