Skip to content

Instantly share code, notes, and snippets.

@kepta

kepta/blog.md Secret

Created February 21, 2018 14:42
Show Gist options
  • Save kepta/f334f43e23dbe4ed1491bf949f9f3f9e to your computer and use it in GitHub Desktop.
Save kepta/f334f43e23dbe4ed1491bf949f9f3f9e to your computer and use it in GitHub Desktop.

Promising Promise Tips

Promises are great to work with! Or so does your fellow developer at work says.

prom

This article would give you to the point no bullshit tips on how to improve your relationship with the Promises.

You can return a Promise inside a .then

Let me make the most important tip standout

Yes! you can return a Promise inside a .then

Also, the returned promise is automatically unwrapped in the next .then

https://gist.github.com/73c44265056e2bdbfc541db798c7f5b1

You create a new Promise everytime you do .then

If you are familiar with the dot chaining style of javascript you would feel at home. But for a newcomer this might now be obvious.

In promises whenever you .then or .catch you are creating a new Promise. This promise is a composition of the promise you just chained and the .then / .catch you just attached.

Let us look at an example:

https://gist.github.com/15e2f805b587dc66ab5460c4373e3536

The relationship of above promises can be described neatly in a flow chart: image

The important thing to note here is that promA, promB and promC are all different promises but related.

I like to think of .thening as a big massive plumbing where water will stop flowing to the children when the parent node malfunctions. For eg. if promB fails, no other node will be affected but if statusProm fails all the nodes will be affected i.e. rejected.

A Promise is resolved/rejected for EVERYONE

I find this as one of the most important things that makes promises great to work with. To put it in other words, if a promise is shared between multiple parts of your app, all of them would get notified when it gets resolves/reject. This also means nobody can ever mutate your promise, so please feel free to pass it around without worrying.

https://gist.github.com/453b4f9833f8513463962ae57e696da9

In the trivial example above you can that promise by design makes it difficult for anyone to do nefarious things. As I said above, Keep calm and pass promise around

Promise Constructor is not the solution

I have seen fellow developers exploiting the constructor style everywhere, thinking they are doing it the promise way. But this is a big lie, the actual reason is that the constructor API is very similar to the good old callback API and old habits die hard.

If you find yourself writing Promise constructors everywhere, you are doing it wrong!

To actually take a step forward and move away from callback you need to carefully minimize the amount of Promise constructor's you use.

Let us jump to the actual use case for promise constructor:

https://gist.github.com/c9f19a077b217483d202f24b705399a7

Promise constructor should only be used when you want to convert a callback to promise. Once you have grasped this beautiful way of creating promises, it can become really tempting to use it at other places which are already promisified!

Let us look at a redundant promise constructor

โ˜ ๏ธWrong

https://gist.github.com/9bb9e500222bc50a8f429d0b2791223b

๐Ÿ’–Correct

https://gist.github.com/c346198fe108bd88b763bb5c2e77616e

Wrapping a promise with Promise constructor is just redundant and defeats the purpose of the promise itself.

๐Ÿ˜ŽProtip

If you are a nodejs person, I recommend checking out util.promisify. This tiny thing helps you convert your node style callback into promises.

https://gist.github.com/fc70a86ffe573576448884e1c26ca8fa

Use Promise.resolve

Javascript provides Promise.resolve, which is a short hard for writting something like this:

https://gist.github.com/d483ab44faeca388d9bd47a93690de11

This has multiple use cases and my favourite being able to convert a regular (sync) javascript object into a promise.

https://gist.github.com/dce345727f75188eb22ef04d161fe0bb

You can also use it as a safety wrapper around a value which you are not sure if it is a promise or regular value.

https://gist.github.com/b9f9b37dd4fe74dae32ad8968f719760

Use Promise.reject

Javascript also provides Promise.reject, which is a short hand for this

https://gist.github.com/5a8152563718ff58dc8e5387ece3e156

One of my favourite use case is rejecting early with Promise.reject.

https://gist.github.com/6c08eca2833076356f502163f329427c

In simple words, use Promise.reject wherever you want to reject promise.

In the example below I use it in a .then

https://gist.github.com/832a03ad1bcf07ab55845aa9129e3412

Note: You can put any value inside Promise.reject just like Promise.resolve. The reason you often find Error in a rejected promise is that it is primarily used for throwing an async error.

Use Promise.all

Javascript provides Promise.all, which is a shorthand for โ€ฆ. well I can't come up with this ๐Ÿ˜.

In simple words Promise.all

https://gist.github.com/411924a25c670b51360cac7562af1a87

The following example shows when all the promises resolve:

https://gist.github.com/201f68a2dc2eb7c498096eca1cd66689

This one shows when one of them fails:

https://gist.github.com/2da0041727213f9a6c827644fcc136e2

Note: Promise.all is smart! In case of a rejection, it doesn't wait for all of the promises to complete!. Whenever any promise rejects, it immediately aborts without waiting for other promises to complete.

Do not fear the rejection OR

Do not append redundant .catch after every .then

How often do we fear errors being gobbled up somewhere in between?

To overcome this fear, I give you a very simple tip:

Make the rejection handling the problem of the parent function.

Ideally, rejection handling should be at the root of your app and let all the promise rejections trickle down to it.

Do not fear writing something like this

https://gist.github.com/9cc7a4fcccffd37ebea7c7ced00914b2

Now if you do want to handle the rejection in your function, decide whether you want to resolve things or continue the rejection.

๐Ÿ’˜ Resolving a rejection

https://gist.github.com/ce14343b3231607c15208ce725d032c1

๐Ÿ’”Rejecting a Rejection To reject a rejection is simple, don't do anything. As I said above, let it be some other functions problem. More often than not, parent functions have a better way to handle the rejection than your current function.

The important thing to remember is, once you write a catch it means you are handling the error. This is similar to how sync try/catch works.

If you do want to intercept a rejection: (I highly recommend not!)

https://gist.github.com/f7936dedfbe5201cf2974986f08ea2fe

The fine line between .then(x,y) and then(x).catch(x) The .then accepts a second callback parameter which can also be used to handle errors. This might look similar to doing something like then(x).catch(x), but both these error handlers differ in which error they catch.

I will let the following example speak for itself.

https://gist.github.com/d449d19737d16e15a96d61f92404251b

The .then(x,y) comes really handy when you want to handle an error coming from the promise you are .thening and not want to handle from the .then you just appended to the promise chain.

Note: 99.9% of the times you are better off using the simpler then(x).catch(x) .

Avoid the .then hell

This tip is pretty simple, try to avoid the .then inside a .then or .catch. Trust me it can be avoided more often than you think.

โ˜ ๏ธWrong

https://gist.github.com/9f9071c49b8e510d80dc9aacdf4aa5ba

๐Ÿ’–Correct

https://gist.github.com/18166054ef0615a13637021d34e7e9ba

Sometimes it does happen that we need multiple variables in a .then scope and there is no option but to create another .then chain.

https://gist.github.com/6854de99aa5d457f6c1445dfb3d6da8e

I recommend using the ES6 destructuring power mixed with Promise.all to the rescue!

https://gist.github.com/36a760d233e4d94213ce04d6eb00fbb1

Note: You can also use async/await to solve this problem if your node/browser/boss/conscious allows!

I really hope this article helped you in understand Promises.

Please check out my previous blog posts.

If you โค๏ธ this article, please share this article to spread the words.

Reach out to me on Twitter @kushan2020.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment