Why are exceptions used for rejecting promises in JS? [closed]

Why wasn’t the api designed in such a fashion where for the then function, it is passed a resolve and reject function like the original promise constructor?

Actually, the API in that spec emerged as a consensus amongst various implementations. However, some points that might have led to this are:

  • then is a rather functional method. It’s callback only should receive one data argument, the result value of the promise.
  • Passing additional resolve/reject functions to the callback does not work well with multiple arguments or even variadic functions.
  • then is usually used as a plain mapping function. You simply return the new value, no resolve is needed.
  • When you really want to do something asynchronous in your callback where you could make use of resolve/reject, you better should use a promise anyway – which you simply can return then.

I once implemented a Promise lib with optional resolve/reject arguments, but it was tedious to use – and I seldom needed them because of #4. Using them was error-prone, you could easily forget something (like handling errors, or progress events) – just like the people who are manually constructing and returning deferreds that are resolved from promise callbacks, instead of calling then.

Exceptions are heavy so it seems odd they are using them as a choice for flow control.

They’re not really meant to be used for control flow (like branching, loops etc) but for exception handling: rejections are exceptional. Most Promise developers wanted to implement them as an alternative for synchronous (blocking) code – where IO was always throwing exceptions, so they adapted this. Rejections are still explained as the asynchronous equivalent to try … catch, though their monadic nature could be utilized in mightier ways and higher-level applications.

Creating a whole new promise object and returning it, just to reject it, adds to code bloat IMO.

There’s not much difference between return new RejectedPromise(…), return reject(…) and throw Error(…).

Debugging becomes harder too in case of an exception is thrown (such as syntax errors, or if function is being called on a undefined object, etc.)

Most Promise developers seem to see this as an advantage actually – (unexpected) exceptions even in asynchronous code will be caught automatically, so they can be handled instead of blowing up the program (unnoticed). See also exception handling, thrown errors, within promises and acceptable promise pattern for ‘LOUD’ errors?.

Leave a Comment