Jordan
Jordan

Reputation: 431

When is async, await, promise.all needed in JavaScript?

I'm trying to improve code performance and after years of coding find myself confused about some fundamentals. Of course we essentially have things that need go in order (async functions) and things in parallel (just normal functions which are synchronous ). I read about promise.all and setTimeout type examples and tried to make a big function rewritten with all these fundamentals and was throwing async on every function and when I finished it was way slower than it was before and now am realizing that async is not as prevalent as I thought but am confused.

If I have the function

function count(n){
  let num = 0
  for(let i = n; i--;){
    num++
  }
  return num
}

and throw in like 140000000 then that is going to take a second to complete. If I need the returned value for the rest of a function to continue I was thinking I would need to await the response so that I could use the response going forward

async function doSomething(){
  const one = await count(140000000)
  const two = count(one)
  return two
}
async function count(n){
  let num = 0
  for(let i = n; i--;){
    num++
  }
  return num
}

But in fact I think its not so much as a value I need to pass into the next function for it to work so its basically fine without awaiting the response because its basically sending a function as the parameter like

async function doSomething(){
  const two = count(count(140000000))
  return two
}

function count(n){
  let num = 0
  for(let i = n; i--;){
    num++
  }
  return num
}

Similarly like synchronous type tasks I thought I would need to use Promise.all to speed things up for concurrently running functions and the functions it takes should be async because it returns a promise that way like

async function parent2(){
  console.log('start')
  console.time('ALL')
  const numsToCount = [ 140000000, 170000000, 240000000 ]
  const res = await countNums2(numsToCount)
  // do other stuff with res
  const fin = count(res[0])
  console.timeEnd('ALL')
  console.log('end', fin)
}

async function countNums2(numsToCount){
  let countedNumsPromises = []
  for(let i = numsToCount.length; i--;){
    countedNumsPromises.push(count2(numsToCount[i]))
  }
  return Promise.all(countedNumsPromises)
}

async function count2(n){
  let num = 0
  for(let i = n; i--;){
    num++
  }
  return num
}

But then again realized I didnt really need promise.all even though its three functions that take some time but can be run together and could just do

function parent1(){
  console.log('start')
  console.time('ALL')
  const numsToCount = [ 140000000, 170000000, 240000000 ]
  const res = countNums(numsToCount)
  console.timeEnd('ALL')
  console.log('end', res)
}

function countNums(numsToCount){
  let countedNums = []
  for(let i = numsToCount.length; i--;){
    countedNums.push(count(numsToCount[i]))
  }
  return countedNums
}

function count(n){
  let num = 0
  for(let i = n; i--;){
    num++
  }
  return num
}

And when you start nesting things like 3 times and more complex things obviously is confusing as well but perhaps trying to get some of these more basic understandings figured out will help with everything. Like doing

const parents = [
 {name: 'Jon', pets: ['dodo', 'goofy']},
 {name: 'Tammy', pets: ['gigi', 'laffy', 'bigbird']},
 {name: 'Tom', pets: ['ralphy', 'goose']},
]

const res = await Promise.all(parents.map(async parent => {
  const res2 = await Promise.all(parent.pets.map(async pet => {
   ...
  }
}

Also would a wait function like in many examples be different than just a slow count function?

async function doSomething(){
  await Promise.all([wait(1000),wait(2000),wait(1500)])
  wait(1000)
}

async function wait(ms){
  return new Promise((resolve) => setTimeout(resolve, ms));
}

So maybe I'm throwing a lot at you here but basically how do I implement synchronous programming and what not for speed properly and what is proper use of async and promise.all vs just passing all the functions into each other as needed and letting the functions figure out all the waiting on the previous function. Also side note I seemed to find that map reduce and filter were not perhaps the fastest because you would be looping over the same data multiple times so unlike that example above I was trying to stick to more for loops but yeah I don't want that to distract from answering question but that is direction I'm trying to go.

Upvotes: 0

Views: 419

Answers (1)

Nicholas Tower
Nicholas Tower

Reputation: 84912

Promises (and thus async/await) aren't a tool to take synchronous code and speed it up. When you create a promise it's usually because you're not calculating anything at all, but instead are waiting for something external to happen.

For example, you might be waiting for a network response to get back, or you might be waiting for a timer to elapse, or waiting for someone to press a key. You can't do any work while this is happening, so instead you create a Promise and then stop running any code. Since javascript is single threaded, stopping running your code is important to let other code start running, including the browser's normal page-painting code.

Promises are objects with .then function on it. You can call .then and pass in a function to tell it "hey, when you're done waiting, please call this function". async/await just simplifies the syntax for working with promises: an async function will automatically create a promise, and awaiting a promise will automatically call .then on it.


With that in mind: The examples you gave don't have anything to do with async await. You have a bunch of synchronous computations, and are not waiting for anything external. Slapping await on a map function or a for loop will have no effect, other than to confuse your coworkers and very slightly increase runtime.

Upvotes: 1

Related Questions