A promise is agnostic to your concern. Thanks for writing.
There may be some utility in being able to pass them around so that the code that calls the API isn't the place where the block occurs, but I'm not convinced it's worth the extra complexity and API fragmentation to care about that.
In my experience of using fibers in ruby (which I _think_ are substantially/exactly the same as coroutines?), it hasn't been like you describe at all -- promises, or something other higher level abstraction, are still pretty neccesary to do useful and comprehensible things with them. So my experience colors my understanding and I think "What's he talking about, that doesn't make any sense."
More likely, you have experience in a language where things are done differently enough that it all comes out different.
What language?
val resultA = something()
val resultB = somethingElse()
return resultA + resultB
With Futures, the processing for resultA and resultB would be done in parallel, because the call to something() does not block. To combine them you don't even need to wait for the processing to finish, because you just create another Future.Also, being able to pass them around is a really important use-case and Futures are also all about error handling. With Scala it's really trivial to wrap the async support in Servlets 3.0 and make your controllers return Future responses. Then in the servlet you just attach onComplete and onFailure events to return the request when it's ready or when it fails. Works like a charm.
The greatest thing about Futures is that the concept is entirely agnostic to the underlying implementation details. You could have a Future result that's being processed asynchronously by an IO loop (e.g. ning's AsyncHttpClient), you could have a Future result that's being processed by a thread and you can combine the results.
If anything, I don't think you worked with Futures much. You should try it out in Scala, where Futures (from Akka or Scala 2.10) are modelled as monadic types, making them highly composable. Doing multi-threading with Futures in Scala is like working with Lego blocks.
https://developer.mozilla.org/en-US/docs/JavaScript/New_in_J...
See http://taskjs.org/ for how it could work in ES6.
If you want to carry the analogy even further generators can also implement coroutine patterns, if you use yield as an expression (for communication) and yield from to do nested generators.