Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there any (negative) side effects when I don't use the "then" function of a Promise?

I have a function which returns a Promise.

Now, sometimes it makes sense for the consumer to use the "then" function on that Promise. But sometimes the consumer simply does not care about when the Promise resolves, and also not about the result - in other words the same function should also be able to be called in a "fire and forget" manner.

So I want these two usage scenarios:

func().then( ... ); // process Promise
func(); // "fire and forget"

This apparently works, but I wonder if this is considered "bad practice", and in particular if this usage pattern could have any unwanted side effects, ie. leading to memory leaks? Right now I am using bluebird, but I consider to switch to native Promises if that makes any difference.

like image 636
frontend_dev Avatar asked Sep 19 '15 16:09

frontend_dev


People also ask

What happens if you resolve a promise twice?

No. It is not safe to resolve/reject promise multiple times. It is basically a bug, that is hard to catch, becasue it can be not always reproducible.

What happens if neither resolve nor reject is called within a promise?

A promise is just an object with properties in Javascript. There's no magic to it. So failing to resolve or reject a promise just fails to ever change the state from "pending" to anything else.

Do you have to await promises?

No, you don't always need to await a promise. But, to ensure proper application flow, you should always be ready to handle any error that occurs. You can choose to not do that, but as you've already stated: if an error occurs and you do not try / await / catch the promise or .

Can you await a promise twice?

The implication of this is that promises can be used to memoize async computations. If you consume a promise whose result will be needed again later: consider holding on to the promise instead of its result! It's fine to await a promise twice, if you're happy to yield twice.


1 Answers

Remember that every call to then results in a new promise. So any Promise implementation that had a memory leak as a result of a promise not having any resolution handlers attached would be a broken implementation, what with all those promises that we never hook handlers to being returned. I very much doubt implementations of ES2015's promises, Bluebird, Q, etc. have that behavior.

Separately, as conceptually a promise's resolution handlers are basically just functions stored by the promise and then called when appropriate, it's not likely to be a memory leak if you never give it any functions to store.

But, there is a problem with your fire-and-forget, just not a memory leak problem: It breaks one of the main Promise rules: Either handle rejection, or return the promise chain to something else that will handle rejection. Since you're not doing that, if the operation fails, you'll have an unhandled rejection. Unhandled rejections are reported to the console and in some environments may terminate your app (at some point, Node.js may start terminating the process when this happens, see this open issue).

If the fact that then returns a new promise is a surprise, consider:

let p1 = new Promise(resolve => {
  setTimeout(() => {
    resolve('a');
  }, 100);
});
let p2 = p1.then(result => {
  console.log("p1.then got " + result);
  return 'b';
});
p2.then(result => {
  console.log("p2.then got " + result);
});

which outputs

p1.then got a
p2.then got b
like image 177
T.J. Crowder Avatar answered Oct 21 '22 12:10

T.J. Crowder