The Promise API's true value lies in lifting control out of the compiler's hands, and into the hands of our runtime, using a very simple structure. Rather than the syntax of the source code being the only description of the relationship between pieces of code (e.g. a callback pyramid), now we have a simple API for storing and using those relationships.
TL;DR The core API of a Promise object should be:
.wait(cb) # cb gets (err, result) .finish(result) # cb will get (undefined, result) .fail(err) # cb will get (err, undefined)
In the public Promises API
.then() establishes such a relationship, but fails in a number of ways for me. The word 'then' is given a second meaning, already being used in "if this then that". If not literally in your language (CoffeeScript), then in your internal dialogue when you are reading and writing conditional expressions of all kinds, such as this sentence.
I find that people who are new to Promises take a long time to 'boot up' to seeing how valuable they are, and the abstractness of
then is part of the problem.
What is the core service that the API should provide? To cause some code to
wait for other code to either
I suggest that
wait is the most accurate verb for the action here, and communicates immediately why I would want to use promises... because I need some code to
wait for the promise to deliver.
then values the lyricism of the resulting code over it's actual clarity, making it just a bit too clever.
Extensions to the API:
"I promise to touch all the files" is an example of a hard promise to make currently, when each touch is asynchronous, since you don't know which file is the last, or when they are all complete. What you need are incremental promises.
promise.progress(current, [maximum]) # emits 'progress' events promise.finish(delta) # calls .progress(current+delta)
"I promise to recurse over all directories", is extra hard because you don't even know the size of the goal at the start, and must update that knowledge recursively.
# only finish() promise after b has finished promise.include(promise_b)
This allows the creation of promises that are both recursive and incremental, which lets you create a tree of promises inside any workload, without leaking knowledge to (or requiring it of) the waiting code.