In javascript, the code is executed line by line while JS keeps track of the function being called with a call stack.
PROBLEM: 😡
As we mention, JS is single threaded, which means it can execute one commande at a time.
So, with that being said, if a line of code takes time to be executed, all the rest of code won't execute till this line finish. Which is the case for external api call.
Then, we want a way to run our code especially long tasks without blocking further code execution.
SOLUTION: 😃
We execute long running task in background without blocking the rest of code until we get back a result.
Promises:
From MDN:
The Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting value.
Promises are simply javascript objects returned the moment we execute asynchrounous task.
This object holds mainly three properties:
onFulfilled: It contains the function to be executed in case of returned data
onRejected: It contains the function to be executed in case of error
value: Contains data returned by the asynchrounous task, that will be automatically in either onnFulfilled or onRejected function parameter.
onFulfilled/onRejected functions get notified when data or error returned, then one of them get added to the microtask queue waiting till call stack become empty and the global execution finishes running to be able to run.
OnFulfilled function is passed to the promise through .then(), onRejected is passed through .catch().
we note that .then() can hold both of them :
.then(onFulfill,onReject)
CREATE YOUR PROMISE:
const createdPromise = new Promise((resolve, reject) => {
const x=10;
if(x==10)
resolve("YAY!");
else
reject("FAIL!");
});
createdPromise.then(
(v) => console.log(v), //YAY!
(err) => console.log(err)
)
We create a promise through Promise constructor to wrap a function and make it returns a promise. This function has two callbacks functions:
resolve: executed when what we were doing succeed
reject: when it fails
You can simulate asynchronous execution above by adding settimout function.
PROMISE EXECUTION:
function runningFor300MiliSeconds() {
//
}
function runningFor200MiliSeconds() {
//
}
runningFor300MiliSeconds();
const futureData = fetch("api-url"); // for 20 ms
futureData.then(
(data) => console.log(data),
(error) => console.log(error)
);
runningFor200Miliseconds();
Here in the call stack we have runningFor300MiliSeconds function running from 0 ms to 300 ms.
From 301 ms fetch function is called and returns a promise object (futureData).
From 302 ms runningFor200MiliSeconds function is added to the call stack and executed till 502 ms.
Meanwhile, in 321 ms futureData value is returned and onFulfilled function is added to the microtask queue waiting for the call stack to become empty.
In 502 ms runningFor200MiliSeconds finished running, the call stack is empty then, onFulfilled function get added to the call stack and executed.
Async/Await:
Async/await tries to simplify promises way of handling returned result, through elimating .then/.catch blocks.
async function foo() {
try {
const futureData = await fetch("api-url");
console.log(futureData);
} catch (err) {
console.log(err);
}
}
// this code is similar to
const futureData = fetch("api-url");
futureData.then(
(data) => console.log(data),
(err) => console.log(err)
);
Asynchrounous Javascript :
Promises and async/await changed the way js works from single threaded blocking execution to non-blocking execution with the help of event loop and microtask queue.
Hope this quick article makes it easier for you to dig deeper into asynchronous javascript concepts and methods. 👏
✌️
Top comments (0)