Asynchronous programming in javascript

Asynchronous programming is a technique in which parallel programming is achieved within a single thread. In synchronous programming, instructions are executed in sequence. But in async programming, instructions may not be executed in a sequence specified in the file. Program does not wait for blocking operation like reading from file/network.

//JS engine delegates the async function to web API which starts the timer
//after the timeout event (or any other event e.g. click),web api adds the callback function to callback queue
//event loop keeps on checking the call stack.
//It checks the callback queue continously 
//when call stack is empty and there some tasks in callback queue, task is given to JS engine for execution
let a = 10
setTimeout(()=>{console.log("asynchronous hi")},1000)
console.log("Synchronouse", a)

Queues in JS

There are 2 types of queues.
  • callback/task queue - e.g. setTimeOut
  • microtask/job queue - e.g. promises

Callbacks

Historically we have been using callbacks to run code asynchronously. But due to callback hell, promises were introduced.

setTimeout(()=>{ console.log("first task") 
setTimeout(()=>{ console.log("second task")
setTimeout(()=>{ console.log("Third task") },1000) },1000) },1000)

Promises

A promise is nothing but the task that needs to be done asynchronously. A promise is an object that may get resolved or rejected or remain in pending status and produce the output. Promise can be in 3 states
  • fulfilled
  • rejected
  • pending

async function f1() {
  return new Promise((res, rej) => {
    setTimeout(res, 1001);
  });
}

let p1 = new Promise(async (resolve, reject) => {
  console.log("My Promise P1 Pending");
  await f1();
  resolve("Passed");
});
p1.then(() => {
  console.log("My Promise P1 resolved");
});

setTimeout(() => {
  console.log("First");
}, 1000);

let p2 = new Promise((resolve, reject) => {
  console.log("My Promise P2 Pending");
  resolve("Passed");
});
p2.then(() => {
  console.log("My Promise P2 resolved");
});

console.log("Last");
Important things to note about Promises
  • Promises allows us to write neat code that looks like synchronous. But it is not.
  • Any function that returns a promise is a producer.
  • then, catch, finally are consumers which run when promise is ready(either resolved or rejected or thrown error)
  • promise.then(fulfilhandler,rejecthandler).catch(errorhandler)

fetch('https://api.github.com/users/reply2sagar')
.then(
//first argument is a function that runs when promise is fulfilled
(fulfilledResult)=>console.log("Fulfilled", fulfilledResult), 
//second argument is a function that runs when promise is rejected
(rejectedResult)=>console.log("failed", rejectedResult)) 
.catch(err => console.log(err))

let firstTaskPromise = new Promise((resolve,reject)=>{
  resolve("first task")
})

let secondTaskPromise = new Promise((resolve,reject)=>{
  resolve("second task")
})

let thirdTaskPromise = new Promise((resolve,reject)=>{
  resolve("third task")
})

firstTaskPromise.then(
 (result) =>{ 
     console.log(result)
     return secondTaskPromise
 }).then(
 (result) =>{ 
     console.log(result)
     return thirdTaskPromise
 }).then(
 (result) =>{ 
     console.log(result)
 })
 
//real life example

/*
-  You can fetch below url from any domaon as acces control allow origin is 
set to *
- https://api.github.com/users/reply2sagar - Access-Control-Allow-Origin: *
- fetch("https://api.github.com/users/reply2sagar").then((res)=> res.text()).then((text)=>console.log(text))
*/

fetch('https://api.github.com/users/reply2sagar')
.then(function(response) {
  return response.text();
})
.then(function(text) {
  console.log(text); 
});


Array of Promise objects

  • Promise.all - It resolves only when all promises resolve. if all promises are resolved, it returns the array of promise result.
  • allSettled - It always resolves even though one of the promise gets rejected
  • race - waits only for the first settled promise and gets its result (or error).
  • any - even though second promise is rejected, it keeps waiting for other promises until one of them is fulfilled. if all promises are rejected, error comes - AggregateError: No Promise in Promise.any was resolved

let urls = [
  'https://api.github.com/users/reply2sagar',
  'https://api.github.com/users/donald'
];

// map every url to the promise of the fetch
let requests = urls.map(url => fetch(url));

Promise.all(requests)
  .then(responses => responses.forEach(
  response => console.log(response.url, response.status)))
  .catch(err => console.log("error oc", err))

Promise.allSettled(requests)
.then(promise => console.log(promise))
.catch(err => console.log(err))

Promise.race(requests)
.then(promise => console.log("prom", promise))
.catch(err => console.log("errrr", err))

Promise.any(requests)
  .then(promise => console.log("prom", promise))
  .catch(err => console.log("errrr", err))

async await


let response = await fetch("https://api.github.com/users/reply2sagar");
console.log(response)

async function f() {

let promise = new Promise((resolve, reject) => {
  setTimeout(() => resolve("done!"), 1000)
});

let result = await promise; 
// wait until the promise resolves (*)

alert(result); // "done!"
}

f();



let results = await Promise.all([
  fetch(url1),
  fetch(url2),
  ...
]);

Promisification

Before promises were added JavaScript, we used to use callbacks. But we can convert old callback based functions into promises easily. This process is called as promisification.

Web development and Automation testing

solutions delivered!!