DEV Community

Cover image for I promise I won't callback anymore

I promise I won't callback anymore

Damien Cosset on September 28, 2017

Introduction Dealing with the asynchronous nature of Javascript can be very challenging and frustrating. Callbacks have been for a long ...
Collapse
 
ben profile image
Ben Halpern

This really gets to the bottom of the benefit. I used to really hate writing async JS, and now it's really quite pleasant.

Collapse
 
mrm8488 profile image
Manuel Romero
Collapse
 
developius profile image
Finnian Anderson • Edited

Promise.all is super useful when you've got a ton of promises to execute, although I intensely dislike how it returns an array of the results - it would be nice to have some way of naming them before passing them in (object?) because otherwise you end up just assigning them all, which I find ugly:

Promise
  .all([ p1, p2, p3 ])
  .catch(console.log)
  .then(data => {
    let user_data = data[1]
    let stats = data[2]
    let other_info = data[3]
})

This would be nicer:

Promise
  .all({ user: p1, stats: p2, info: p3 })
  .catch(console.log)
  .then(console.log)

/*
{
  "user": user_data,
  "stats": stats_data,
  "info": info_data
}
*/

Collapse
 
damcosset profile image
Damien Cosset

I haven't used Promise.all very often. I think I agree with the returned array being weird. You can pass an array of objects:

Promise.all([{time: promiseToBeHereOnTime(true)}, {love: promiseToLove( true )}, {protect: promiseToProtect( true )}] )
.then(content => {
  console.log(content)
  console.log('Done! All fulfilled')
})
.catch(err => {
  console.log(err)
})

/*
[ { time: Promise { 'I promise I will be there!' } },
  { love: Promise { 'I love you so much!' } },
  { protect: Promise { 'I promise I will protect you!' } } ]
Done! All fulfilled
*/

I don't know, it probably would be easier to tweak the Promise.all implementation to server a specific purpose.

Collapse
 
developius profile image
Finnian Anderson

You still have the problem with an array being returned though - it's ugly. Named properties would be much nicer. The specific purpose would be to avoid this:

Promise
  .all(proms)
  .then(data => {
    let a = data[0]
    let b = data[1]
    let c = data[1]
    doSomethingWith(a)
    doSomethingWith(b)
    doSomethingWith(c)
  })
  .catch(console.log)

And replace it with this:

Promise
  .all(proms)
  .then(data => {
    doSomethingWith(data.a)
    doSomethingWith(data.b)
    doSomethingWith(data.c)
  })
  .catch(console.log)
Collapse
 
developius profile image
Finnian Anderson

Just spotted this, which gives another interesting approach. Still too much code duplication for my liking though. dev.to/mrm8488/using-es6-array-des...

Collapse
 
kspeakman profile image
Kasey Speakman

The normal behavior like you demonstrate with the last examples is nice. I do find really confusing the behavior of a then after a catch. It behaves like a "finally", but that's somehow unexpected to me.

Collapse
 
damcosset profile image
Damien Cosset

Agreed, it is a bit confusing. A lot of librairies/packages implement a finally method, hopefully we will see it soon. I wonder if they are thinking about adding it in the future spec

Collapse
 
robihood23 profile image
Robert Gogolan • Edited

@Finnian Anderson

I guess you can try to use destructuring in the handler

Promise
  .all([ p1, p2, p3 ])
  .catch(console.log)
  .then(([user_data, stats, other_info] = data) => {
     doSomethingWith(user_data)
     doSomethingWith(stats)
     doSomethingWith(other_info)
})

or directly

Promise
   .all([p1, p2, p3])
   .then(([p1result, p2result, p3result]) => {
    console.log(p1result, p2result, p3result);
   })
Collapse
 
math2001 profile image
Mathieu PATUREL

const { promisify } = require('util')

So neat!! Didn't know about this function. Also note that if you want to have this already done, you can use mz (I was gonna say fs-promise, but it's been deprecated...).

Next step: async and await!

Collapse
 
damcosset profile image
Damien Cosset

Oh, I didn't know about mz package, good to know.

Yep, now I have to explore async/await. Seems like the new logical wait to deal with asynchronous stuff in Javascript

Collapse
 
nickytonline profile image
Nick Taylor

Nice write up! I think it's really great that they added util.promisify. You should do a follow up to this post on async/await. πŸ”₯

Collapse
 
bengreenberg profile image
Ben Greenberg

This is great, thanks!

Collapse
 
mrm8488 profile image
Manuel Romero

Using E6 Array destructors is so handful for Promise.all -> medium.com/@3f2bb9b4510b/7a952a8581c3

Collapse
 
adam_cyclones profile image
Adam Crockett πŸŒ€

Good title, ill await your reply 🀣

Collapse
 
tobi418 profile image
tobi418

There is new and better alternative in ES7 named Observable.

Collapse
 
damcosset profile image
Damien Cosset

Ha, don't know about that one. I'll need to explore that.