DEV Community

Brad Hankee
Brad Hankee

Posted on • Updated on

JS Promises.bonus(useCases)

This post will QUICKLY cover the basics of promises then go into the other side of promises rarely talked about(Promise.all(),Promise.allSettled(), Promise.race(), Promise.any()). Great way to discover more uses for promises and impress that interviewer at some point. If you prefer a video version please check out...

JUNIOR DEV LEVEL
Ok so if this isn't the first time you seen Promises feel free to skip to next section. Here is the summary of what a promise is in JS. Promises give us a better way to handle callbacks and more notably the callback hell that many talk about.
Simplified: With more then one callback a pattern that made it difficult to read and maintain JS such as this beauty...

Call Back Hell Example

callOne(args, () => {
  // Wait for One then call Two
  callTwo(args, () => {
    // Wait for Two then call Three
    callThreeRejected(args, () => {    
    })
  })
})
Enter fullscreen mode Exit fullscreen mode

Functions used in examples

 let callOne = new Promise((res, rej) => {
   return setTimeout(res, 3000, "Call One Returned")
 })  

let callTwo = new Promise((res, rej) => {
   return setTimeout(res, 2000, "Call Two Returned")
 })  

let callThreeRejected = new Promise((res, rej) => {
   return setTimeout(rej, 1000, "Call Three REJECTED")
 })  

Enter fullscreen mode Exit fullscreen mode

Common usage chaining promises in sequence



callOne
.then(data => {console.log(data); return callTwo})
.then(data => {console.log(data); return callThreeRejected})
.then(data => {console.log(data)})
.catch(err => console.error(err))

//With Async / Await
async function useAsync(){
  const dataOne = await callOne
  console.log(dataOne)

  const dataTwo = await callTwo
  console.log(dataTwo)

  const dataThree = await callThreeRejected.catch((e) => { 
    console.error(e)})
  console.log(dataThree)
}

useAsync()

Enter fullscreen mode Exit fullscreen mode
console.log
"Call One Returned"
"Call Two Returned"
"Call Three REJECTED"
Enter fullscreen mode Exit fullscreen mode

SENIOR DEV LEVEL
Promise.all([getDataOne, getDataTwo, getDataThree])
Summary:Returns array of all promise data UNLESS one is rejected. Should be named to Promise.allOrNothing()
USE CASE: When results from more then one API call are needed to do something with(display in a ChartJS graph). This makes sense since if one call is rejected the chart cannot be built correctly.


let consumeParallel = async () => {

  let [resultsOne, resultsTwo] = await Promise.all([callOne, callTwo])


  // Use for error handling and comment out prev 7 lines
  // let [resultsOne, resultsTwo, resultsThree] = await Promise.all([callOne, callTwo, callThreeRejected]).catch(err => console.error(err))

  console.log(`All Promises: ${resultsOne} && ${resultsTwo}`) 

}

consumeParallel()
Enter fullscreen mode Exit fullscreen mode
console.log
"All Promises: Call One Returned Call Two Returned"
Enter fullscreen mode Exit fullscreen mode

Promise.allSettled([getDataOne, getDataTwo, getDataThree])
Summary:Wait for no more pending promises (all settled) meaning each either resolved or rejected.
USE CASE: Seemingly few use cases for this (if you have others put in comments please). One that is consistent is using this for indicating when a displayed loader/spinner should be removed from screen.

let consumeSettled = () => {  
  Promise.allSettled([callOne, callTwo, callThreeRejected])
    .then(promiseResults => console.log(promiseResults))
    .catch(e => console.error(e))  
}

consumeSettled()
Enter fullscreen mode Exit fullscreen mode
console.log
[
 {status:"fulfilled", value:"call one returned"},
 {status:"fulfilled", value:"call two returned"},
 {status:"rejected", reason:"call three REJECTED"}
]
Enter fullscreen mode Exit fullscreen mode

Promise.race()
Summary: Takes in iterable such as an array and returns data for the first settled (resolved or rejected) promise.
USE CASE:An interesting use case for .race() is having one promise along with another that resolves with a certain time period in ms and if that one resolves first show a loader/spinner.

let racePromises = async () => {  
  let firstDone = await Promise.race([callOne, callTwo])

  console.log(`First Promise Settled: ${firstDone}`) 
}

racePromises()
Enter fullscreen mode Exit fullscreen mode
console.log
First Promise Settled: Call Two Returned
Enter fullscreen mode Exit fullscreen mode

Promise.any()
Summary: Takes in iterable such as an array and returns data for the first resolved promise.
USE CASE:For a performance use case a developer can use .any() to set up an array of promises if the users are worldwide and more than one server is available. This would allow for the fastest response time from a server.

let anyPromise = async () => {  

  let firstDone = await Promise.any([callOne, callTwo]) 
  console.log(`First Resolved: ${firstDone}`)


}

anyPromise()
Enter fullscreen mode Exit fullscreen mode
console.log
"First Resolved: Call Two Returned"
Enter fullscreen mode Exit fullscreen mode

There you go. Hope this helps at least one person see the potential of using promises and the built in methods it allows.

Top comments (0)