Promise Issues

This line of code from a very good blog post on why promises are a bit dangerous that I tried in my terminal with nodejs:

Promise.resolve({ then: () => console.log("Hello!") })

And you’ll find that any code you type in the REPL doesn’t get evaluated anymore.

Because it never resolves.

The Issue on Promises

In this blog post the Author points out a lot problems that Promises have (read the summary on Promises which details alot of it).

I’m very particular about Point 1 and 3 and I’m going to outline them.

The First Point: Eager Promises

Promises are eager, which sets them up for a variety of issues as well as making them useless for side-effect management. @avaq

Promises are eager because the moment you call a .then() on a Promise it’s going to execute.

Although the type-hints are capable of showing you if a function returns a Promise<T> you may never know if underneath the function that it has already made a .then() call to an external service.

In order for you to know what the heck happened in that function you need to peer into its implementation.

The moment you invoke a Promise returning function the state of the system may have changed

The Third Point: Mixing Exceptions with Expected Failures

Promises mix exceptions with expected failures. @avaq

The things that I’ve learned about genuine exceptions:

  • It represents a real bug in your system (NPEs, undefined properties, etc)
  • Generally you don’t know how to handle them (causes your APIs for example to return a 500 response unintentionally) and when they happen the process crashes.
  • Try-catched at the highest level or at the lowest level

And The things I’ve learned about fake exceptions:

  • Used to represent an expected error(Email/Password validations, Record not found, etc.)
  • Generally custom-made exceptions to be somewhat identifiable (NoSuchRecordException, WeakPasswordException, etc.)
  • Try-catched anywhere and bubbles up the call chain

One thing to note about exception handling is that once an exception occurs in your try {...} blocks is that it jumps directly to your catch {...} block.

The reason it does that is to tell you through the stacktrace what line in your try {…} that went wrong and its this characteristic that makes exceptions just Another form of goto.

If you utilize methods that throw exceptions for expected errors and wrap those methods in a Promise then you can get away with try-catch.

But you would no longer have the ability to branch between handling those expected errors and those geniune exceptions.

Because Promise.catch() mushes them together and you might handle a geniune exception the wrong way instead of letting the process crash and restart.

What I generally do instead is to utilize Folktale’s Result container for such things when dealing with expected errors:

new Promise(someSideEffectThatMayFail()).then(Result.Error, Result.Ok)

Conclusion

TLDR:

  • Promises just unwind side-effects when calling its .then() method making it not safe to call every time(its not idempotent)
  • Don’t use exceptions on expected errors and wrap it in a Promise, instead use some sort of Result Container like folktale’s to represent them and wrap it in a Promise.

And those are my issues on Promises.

The only thing redeemable about them is that they enable async/await.

But that also leads to another issue on function colors.

Comments