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 ... [Read Full]
markdown guide
 

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

 
 

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
}
*/

 

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.

 

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)
 

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

 

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.

 

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

 

@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);
   })
 

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!

 

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

 

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. 🔥

 
 
 
 

There is new and better alternative in ES7 named Observable.

 

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

code of conduct - report abuse