Javascript promise in depth: examples

Javascript promise in depth: examples

Javascript Promise became popular when it was introduced. Javascript promise is mainly used to handle asynchronous tasks. In this article, we will deep dive into promise through examples.

Promise state:

A Javascript promise can have only one state in either fulfilled or rejected.

A promise in a state of fulfillment or rejection is called a promise settled.

Example#1

Promise with resolved state

// Asnc function always return Promsie with resolve or resolve state
async function getMyName(){
  return "Vijendra Rana"
}
//OR
function getMyName(){
   return new Promise((resolve)=>{
     resolve("Vijendra Rana")
})
}
//or
function getMyName(){
 return Promise.resolve("Vijendra Rana")
}

Example#2

Promise with rejected state

// Asnc function always return Promsie with resolve or resolve state
async function getMyName(){
//Throw here return Promise with rejected state with reason
  throw Error("Name not found")
}
//OR
function getMyName(){
   return new Promise((_,reject)=>{
     reject(Error("Name not found"))
})
}
//or
function getMyName(){
 return Promise.resolve(Error("Name not found"))
}

//Error - when promise rejected, provide proper reason using Error

Example#3

Get a response from resolved Promise - By using then() chain method

getMyName().then(res =>{
 console.log("------",res)
})

Example#4

Handle rejected the promise. catch() chain method

getMyName().then(res =>{
 console.log("------",res)
})
.catch(err =>{
//log the reasons
})

Example#5

in then(), we can add resolve and reject handler

//Reject Hanndler

async function getAllNames(id) {
  if (id) {
    return ["a", "b", "c"];
  } else {
    throw new Error("id is undefined");
  }
}

//every Promise has resolve and reject hander

const namePromise = getAllNames(12);
// namePromise
//   .then((res) => {
//     console.log(res);
//   })
//   .catch((err) => {
//     console.warn(err);
//   });

console.log(typeof namePromise);

namePromise.then(
  () => {
    console.log("Resolved");
  },
  () => {
    console.log("Unresolved");
  }
);

Example#6

finally() to clean up purpose.

//finally to clean up

async function getMovies(id) {
  if (id) {
    return ["1", "2", "3"];
  } else {
    throw new Error("Id req");
  }
}

getMovies(12)
  .then((res) => {
    if (!res) {
      throw Error("Unsuccessful attempt");
    } else {
      console.log("data", res);
    }
  })
  .catch((err) => {
    console.log("error-->", err);
    throw new Error("....");
  })
  .finally(() => {
    console.log("more clean up work");
  });

Example#7

Return reject promise from resolve handler when the response is not ok.

//Promise to reject

async function getMovies(id) {
  if (id) {
    return ["1", "2"];
  } else {
    return [];
  }
}

getMovies().then((res) => {
  if (res.length === 0) {
    return Promise.reject(new Error("unsuccessful response"));
  }
}).catch((err) =>{
    console.warn('---!!!!',err);
});

Example#8

Create Promise with Promise constructor.

//Promise Constructor
// const promise = new Promise((resolve, reject) => {
//   // do some async operation then return promise with resolved state
//   setTimeout(() => {
//     resolve();
//   }, [1000]);
// });

//refactor to sleep
// function sleep(ms) {
//   return new Promise((resolve) => {
//     // do some async operation then return promise with resolved state
//     setTimeout(() => {
//       resolve();
//     }, [ms]);
//   });
// }
//further refactor
function sleep(ms) {
  return new Promise((resolve) => {
    // do some async operation then return promise with resolved state
    setTimeout(resolve, ms);
  });
}
//resolve invoked jsut after constructor called not an asynchronous call so if
function Rejectsleep(ms) {
  return new Promise((resolve) => {
    throw Error("+++++");
    setTimeout(resolve, ms);// This line will not be reachable
  });
}

sleep(1000)
  .then(() => {
    console.log("Resolved");
  })
  .catch((err) => {
    console.log("Rejected from resolved promise");
  });

Rejectsleep(1000)
  .then(() => {
    console.log("Resolved");
  })
  .catch((err) => {
    console.log("Rejected from resolved promise");
  });

Example#9

Convert callback to Promise

//convert call back to promise

//read file from fs lib, Node api use callback heavily
// import { readFile } from "fs";
const fs = require("fs");
//this is  callback based
// fs.readFile(__filename, "utf-8", (error, contents) => {
//   if (error) {
//     console.error(error);
//   } else {
//     console.log(contents);
//   }
// });

//convert to Promise based app
function readFile(path, encoding) {
  return new Promise((resolve, reject) => {
    fs.readFile(path, encoding, (error, contents) => {
      if (error) {
        reject(error);
      } else {
        resolve(contents);
      }
    });
  });
}

readFile(__filename, "utf8").then(
  (contents) => {
    console.log(contents);
  },
  (error) => {
    console.error(error);
  }
);

Example#10

Promise.race() - get the fastest settled promise

//Promise.race()

//examplep-1
function resolveAfter(ms, value) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(value);
    }, [ms]);
  });
}

// const pA = resolveAfter(1000, "A");
// const pB = resolveAfter(2000, "B");

// const PResult = Promise.race([pA, pB]);
// PResult.then((val) => {
//   console.log(val);
// });

//Least use of Race  method but in one case
function timeout(ms, promise) {
  let timeoutId;
  const timeoutPromise = new Promise((_, reject) => {
    timeoutId = setTimeout(() => {
      reject(Error(`Operation timed out after ${ms}`));
    }, ms);
  });

  return Promise.race([promise, timeoutPromise]).finally(() => {
    clearTimeout(timeoutId);
  });
}

const promise = resolveAfter(1000, "Promise A");

timeout(5000, promise).then(
  (value) => {
    console.log(value);
  },
  (error) => {
    console.error(error);
  }
);

Example#11

Promise.all() - get all promises when all API calls parallel

//Promise.all

async function getMovieTitle(id){
 return "Iron Man"
}

async function getMovieId(dir, actor){
  return 1
}

// getMovieId("Rachel","RJD").then((res) =>{
//     if(res){
//         getMovieTitle(res).then((t) =>{
//             console.log('++++',t);
//         })
//     }

// })

//If both are independent call then call Parallely
const promsies = Promise.all([
    getMovieId("Rachel","RJD"),
    getMovieTitle(1)
])

// console.log('Fullfilled Promsie',promsies);
promsies.then(([id,title]) =>{
    // const id = res[0]
    // const title = res[1]

    console.log('Id',id, 'Title',title);
}).catch(err =>{
    console.log(err);
}).finally(() =>{
    //do some clean up work
})

//in order Promise to  be fullfilled , all promise must be fullfilled

Example#12

If any promise failed from Promsie.all() then no return one Promsie with rejected state. So Promsie.allSettled()

//Promsie.allSettled
async function getMovieTitle(id) {
  throw Error("Something Wrong!!");
}

async function getMovieId(dir, actor) {
  return 1;
}

//Promise.allSettled always return settlled  promise
Promise.allSettled([getMovieId("Rachel", "RJD"), getMovieTitle(1)]).then(
  ([id, title]) => {
    if (id.status === "fulfilled") {
      console.log(id.value);
    }
    if (title.status === "fulfilled") {
      console.log(title.value);
    }
  }
);

Example#13

Promise. any() - > In the real word, API failed. To make it resilient we can use Promise.any()

//Promsie.any() to make more resilinet in api down time

var promises = [
  Promise.reject(Error("Fail#1")),
  Promise.reject(Error("Fail#2")),
//   Promise.resolve(2),
];

// Promsie.any return fullfilled promise if any Promise is fullfilled

Promise.any(promises).then(
  (value) => {
    console.log("fullfilled ", value);
  },
  (error) => {
    console.warn(error.errors);
  }
);

Example#14

Async/Await - We can use better readable code with async/await keyword from JS.

//Async/Await

function getMovies() {
  return new Promise((resolve, reject) => {
    resolve(["a", "b", "c"]);
    // reject(Error("Erorr Occured"));
  });
}

function getMovies2() {
  return new Promise((resolve) => {
    resolve(["a1", "b1", "c1"]);
  });
}

async function main() {
  try {
    //it is a sequential api call
    // const movies = await getMovies();
    // const movies2 = await getMovies2();
    //parrallel
    const [movies, movies2] = await Promise.all([
      await getMovies(),
      await getMovies2(),
    ]);
    console.log("+++++", movies, movies2);
  } catch (error) {
    console.log("Some error occured");
  }
}

main();

I hope it will help to understand and write promise-based codes in JS.

Next, we will deep dive into Async/Await. Check my articles to know more about technical stuff.

Happy coding :)

Did you find this article valuable?

Support Vijendra Rana by becoming a sponsor. Any amount is appreciated!