DEV Community

9 Promising Promise Tips

Kushan Joshi on February 21, 2018

Promises are great to work with! Or so does your fellow developer at work says. This article would give you to the point no bullshit tips on ho...
Collapse
 
jymbob profile image
jymbob

Nice. I may be in the 0.01% that needs to use .then(x, y) so thanks for explaining the difference

Also in your first example, I'm pretty sure

.then(r => {
    return serverStatusPromise(r); // this is a promise of { statusCode: 200 }
})
.then(

...can be simplified to

.then(serverStatusPromise)
.then(

... because of function currying, assuming ServerStatusPromise accepts one value and returns one value.

This means you can do things like:

fetch('https://example.com/')
.then(validateResponse)
.then(readResponseAsJSON)
.catch(handleResponseError)
Collapse
 
kepta profile image
Kushan Joshi • Edited

I agree that that code can be simplified into the one you mentioned, but in my humble opinion:

  • I personally find it hard to follow what is going on when you simply pass a callback reference.
  • Using this style would make it difficult for new comers to actually understand what is going on.
  • It works fine for unary callbacks like in promises, but it is a source of cryptic bugs when there is an arity mismatch between the caller and the callback.
  • It also becomes a problem when you want pass method which is context (this) sensitive. I have seen folks doing .catch(console.error.bind(console)) just to avoid that, when they could simply have used a .catch((err)=> console.error(err)).
Collapse
 
mgtitimoli profile image
Mauro Gabriel Titimoli • Edited

Hi Kushan,

Thanks for having taken the time to write this, great post.

Just a couple of things that they are not correct:

  1. When you wrote the pseudo code to describe Promise.all, you wrote: then runs all of them simultaneously; which it's not true, as promises given to Promise.all have already started
  2. The "correct" example you wrote for (9), is not entirely OK, it should be like follows:
request(opts)
.catch(err =>
  err.statusCode === 400
    ? request(opts)
    : Promise.reject(err)) // you missed rejecting in your example
.then(r => r.text())
.catch(err => console.error(err));
Collapse
 
kepta profile image
Kushan Joshi • Edited

Hey Mauro,
Thanks for giving the feedback.

  1. Yes I agree, I think I tried to convey that it doesn't do any sort of batch execution, but then promises by design run the moment they are created. I think I should have an additional tip which clarifies about how promises run.

  2. Whoops, missed that, corrected it :)

Collapse
 
brunoscopelliti profile image
Bruno Scopelliti

Hi, since we're talking of Promise, these days I'm publishing a series of videos about how to build a promise polyfill, with the stated goal of making clear how promise works under the hood.
If this sounds as something interesting, here's the first video: youtube.com/watch?v=E_p-PVNqhZE

Collapse
 
annarankin profile image
Anna Rankin

Thanks so much for this! I never knew about Promise.reject/Promise.resolve. Awesome :D

Collapse
 
danielfrugoni profile image
DanielFrugoni

Hi, hope you can help me.
having this:
async searchDatoReg(locclave: string, locmail: string) {
this.mensaje = null;

return new Promise((resolve) => {
this.api.searchProductoLg(locclave, locmail).subscribe(
(data) => {
if (isUndefined(data[0])) {
this.op = 0;
this.filtrados = null;
console.log('tempx1:');
} else {
this.filtrados = { ...data };
this.op = 1;
console.log('tempx2:');

      }
    }
  )
}
)

}
then:
await this.searchDatoReg(locclave, locmail);

   if (this.op === 0){
      console.log('aca 1')
      console.log(JSON.stringify(this.filtrados));
      this.glo.asignaReg(this.filtrados[0].email,this.filtrados[0].clave,this.filtrados[0].nombre,this.filtrados[0].id);
    } else {
      console.log('aca 2');
      console.log(JSON.stringify(this.filtrados));
      this.glo.asignaReg(locmail,locclave,'',0);
    }

dosent syncronize the call, should first do this.searchDatoReg(..) then the rest
but never does it
any hint please

Collapse
 
westc profile image
Chris West

Thanks so much for the post. I always love learning more about JavaScript. In fact, I recently created a topsites site that I think this link belongs on. It is at ciphly.com?languages=JavaScript. Please consider adding this post and other informative ones like it!

Collapse
 
nimatrazmjo profile image
Nimatullah Razmjo • Edited

Hi Kushan,

Thanks for explaining the promise in a very good way especially Promise constructor.

I have a question.

In promise all. I have five promise which runs concurrently. If promise one resolve and promise two got a problem will go directly to catch part of Promise.all. does it rollback the promise one changes or not.

I am a bit confused.

Or let's say. In Promise.all, if an error occurs to single promise. does it rollback all other promises changes?

Thanks in advance.

Collapse
 
kepta profile image
Kushan Joshi • Edited

I am not clear what you mean by rolling back.

Let us look at a modified point 7's example:


const prom1 =  fetchComments().then(comments => console.log(comments));
const prom2 = fetchPosts().then(posts => console.log(posts))


Promise.all([prom1, prom2])
.then(() => {
  console.log('Hello');
})

If I understand your doubt correctly, imagine the above situation in which there are 2 promises prom1 and prom2. Now if prom2 fails because fetchPosts fails, the following things will happen:

  • console.log(comments) would be shown to users, since promises are immutable and prom1 has nothing to do with prom2 failing.
  • console.log(posts) would NOT be shown to users, since prom2 has failed.
  • console.log('Hello') would NOT be shown to users, since it is a new promise composed of prom1 & prom2, in which prom2 has failed.

To understand Promise.all correctly. You need to understand that Promise.all creates a new promise whose outcome is dependant on the promises (eg. prom1 and prom2) it was composed with.

Let us use our previous example and this time name the new promise:

const resultPromise = Promise.all([prom1, prom2]);

// This is exactly same as the previous example, just with improved readability with the help of variable naming
resultPromise.then(() => {
  console.log('Hello');
})

The outcome of resultPromise is:

  • resolved: If all of the promises resolve.
  • rejected: If one or more promises rejects. In our example prom2 rejected and hence resultPromise would also be rejected.

Now you can clearly see the dependency of all these promises and their outcome. (btw reread the point 2, I hope this comment will make it easier).

Collapse
 
yujinyuz profile image
Yujin

thanks for this post! Gave me some idea how to understand Promises on open-source projects :D

Collapse
 
brenonaraujo profile image
Brenon Araujo

Hi kushan,

Thanks for sharing, this post helps me a lot.

Collapse
 
thibmaek profile image
Thibault Maekelbergh

Best promise article ever

Collapse
 
happy32x profile image
happy julien

Thank you very much... You great

Collapse
 
rkristelijn profile image
Remi Kristelijn

Very good read! Finally a simple piece of text that explains how to do stuff and not how to not do stuff.

Collapse
 
amitphulera profile image
Amit Phulera

That is a very informative post on Promises.
Thanks for writing :)

Collapse
 
chardos profile image
Richard Tan

Learnt a lot. Thanks Kushan!