Recently, I've spent a lot of time trying to dive into, and understand, Javascript Promises, especially those adhering to the Promises/A+ spec. What I'm trying to understand is whether or not Promises actually give developers additional tools specifically when compared to CPS based async, or whether it is mostly syntactic sugar and a tool to reduce verbosity or streamline some behaviors.

One argument I've heard for promises is error handling. In that case, using the async library it is very easy to execute a async.waterfall of functions, each waiting for the prior to complete, each wrapped in a try/catch to handle synchronous errors (since neither Promises, nor async handle async errors), passing caught errors to an error handler. In that situation Promises and async behave identically regarding error semantics (gist showing this behavior).

Another argument I've heard for promises is future-proofing methods which are sync now, but asynchronous later on. The theory is that if the function returns a promise, it doesn't matter what if it is modified later. Since both sender and receiver have to modified to adhere to the promise contract, can't the same argument be stated for modifying both sender and receiver to use the CPS contract, even if it's synchronous, to future proof it?

So with that in mind is there any use-case that you can think of which can only be solved optimally by Promises or is their usage really more a case of preference and the desire to reduce verbosity and reduce the chance of error?

  • Promises work well with generators and allow pseudo-synchronous behavior with good stack traces in case of an exception. However there are other constructs working well with generators. Look up Qand co and other packages. – nalply Feb 21 '14 at 8:06
  • This is discussed on SO: task.js generators/promises vs. async callbacks. I found the article it references to also be worth reading (blog.jcoglan.com/2013/03/30/… - scroll to where it mentions "async module"). – Brian Apr 11 '14 at 17:58
  • "since neither Promises, nor async handle async errors" - isn't that what the second argument to Promise's then is for? – Izkata Sep 26 '16 at 21:46

Some of the advantages of promises are that they make asynchronous operations a "first-class" entity. They can be transformed, they are composable, and their use also happens to reduce nesting and make handling of async code more analogous to sync code. To me, it is usually more readable to have a chain of promises than nested callbacks. Many modern languages have moved to promise-style async.

See: http://domenic.me/2012/10/14/youre-missing-the-point-of-promises/

  • In the document linked, I believe the assertion about asynchronous execution and exceptions is wrong: with asynchronous execution one could catch exceptions thrown by an object rather than from an execution scope. – Hibou57 Nov 30 '16 at 15:46

I believe the two main benefits of Promises are:

  1. Much more readable code that describes the sequence of operations clearly. I think of "sugar" as saving typing or obscuring (often magic) complexity, whereas in this case, what's more salient is providing greatly increased clarity and therefore more solid, less error-prone code. As Knuth said, code is primarily for humans, and incidentally is executable by computers.

  2. Ability to ignore whether an operation has already completed or not at the time the calling code executes. This is different than future-proofing, which is about being agnostic at the time of writing the code. Some Promise implementations allow returning promise objects that have already resolved but can still have then() called. Sometimes this nicely deals with otherwise race conditions.

I'm not deeply experienced with them, but I don't believe there are any significant advantages other than the above. But, the above are very big advantages.

The one disadvantage I've run into is using different libraries whose Promise implementations had subtle differences, like the behavior of calling then() on an already resolved promise. Also the problem that where library A (ngluar, *cough*) could accept promise objects in many places, but was using explicit rather than duck typing, you'd get into annoying situations where you have to wrap library B's promise's with library A's promises, having the opposite effect of sugar. This is basically a side effect of Javascript having neither native Promises nor any mechanism for a standard library, but it is a real world caveat.

Also the terminology is slightly silly. Thenable?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.