DEV Community

BebopVinh
BebopVinh

Posted on

My Take on Async JavaScript Promises with Concurrency Limit

In a recent interview, I was asked to go under the hood of a Promise and explain how it would work with a concurrency limit. Having only focused on how Async/Await made everything so much easier to read and write, I blanked out. While I did my best to attempt at it, I couldn't explain it well enough to pass the tech interview.

Disclaimer: Below is my first impression and attempt at comprehending what a Promise and Concurrency really are. I still have much to go on and am really open to any corrections/advice to this post. Sources linked below.

Promise?

Okay, a Promise is an object to be fulfilled at a later time provided by the Web API. It can be resolved or rejected. If resolved, a .then chain can be run on the result. If rejected, a .catch will handle the errors. Both .then and .catch takes a callback functions and let you manage your Promise however you like.
Paraphrase: As best explained by Kyle Simpson, getting a Promise is like going to a burger-joint and ordering a burger. You don't get a burger instantly, as they have to make-to-order. Instead, you get a receipt, which then lets you exchange it for the burger you order once it is ready.

The structure of a promise is like this (as shown by Beau):

   //structure of a Promise
   let myPromise = new Promise(function(resolve, reject) {
      if (conditions are met) {
         resolve('Done!')
      } else {
         reject('Something went wrong!')
      }
   })
   //chaining a `then` when resolved
   .then(result => {return result})
   //chaining a `catch` when rejected
   .catch(error => console.log(error))

There's other things regarding Promises that I won't go over. Such as try/catch which basically lets you wrap your Async operations in a try block and it will call catch if anything inside the block goes wrong.

There's also Async/Await, which is like syntactic sugar for writing async functions and make them read like synchronous things. Check out the video by Brad Traversy below, it makes life simpler! I wasn't allowed to use this, though.

Concurrency Limit

My best take on these two words is how many Promises can run or should be running at a given time interval. Given a limit (say 10 Promises at a time) and an array of Promises (say 100 elements), the solution function should run 10 Promises in parallel and queue up the next Promise should one of them complete. This repeats until all the Promises are resolved.

In comes Promise.all(), which is a Prototype method that returns a super ultimate Promise (I'm making this up) once all the Promises are resolved.

Here's my stab at this after reading and watching some materials. I did even worse in the interview.
Warning: Broken code below!

const limit = 10
let promiseBatches = []
let promiseArray = [] //realistically would be filled with Promises to be resolved
function promiseBatch(promiseArray, limit) {
   let batch = []
   i = 0
   //run 10 promises while there are still 10 promises
   while i < limit && promise.Array.length > 0 {
      let promise = promiseArray.shift()
      i ++
      batch.push(promise.resolve())
   }
   //adds batch to big batches array for Promise.all()
   promiseBatches.concat(batch)

   //recursive until promiseArray is empty, else return Promise.all() of the batches
   if promiseArray.length > 0 {
      promiseBatch(promiseArray, limit)
   } else {
      return Promise.all(promiseBatches)
   }
}

I'm pretty sure I'm still wrong. Any thoughts?

Sources

Promises explained by Beau from FreeCodeCamp

Event Loop by Philip Roberts

Advanced Async and Concurrency Patterns by Kyle Simpson

Async/Await by Brad Traversy

Oldest comments (0)