I've become interested in futures lately, mostly due to their inclusion in standard C++ - but I see there is an active debate over futures vs. callbacks in many programming areas, such as Node.js.
I'd like to ask is if there are any well-known patterns/use-cases where futures provide a clear advantage (in terms of readability and ease of implementation) to callbacks?
The advantage of using futures is they eliminate the code indirection and let you write code in a "synchronous" style, but provide you with a handler that lets you check on the status of some background operation. In that sense, I don't think it would be too subjective/controversial to claim that futures are a better syntactic fit with how the human mind tends to think (do this, do that, do this while waiting for that, etc).
However, when I actually use futures in practice, I often run into the following issue:
A typical use case for futures is where you manage many async operations via an array of future objects, like a
vector<future> futures (using C++ syntax). I think a key insight is that futures require that you actively check each async operation to see if it's done, whereas with callbacks you passively wait for each event to complete. But since, in the general case, you have no way of knowing which event will complete first, you may lose out on some parallelism if you're iterating over an array of futures and
future finishes 5 seconds before
future, but you're sitting there waiting for
future to complete.
We can mitigate this with a "wait_for" type of operation - instead of waiting on each future, we can wait for a certain short interval, and then proceed to continue iterating. But this is basically like busy waiting, consuming extra CPU resources. With callbacks, you wouldn't need to do any of this because callback code is invoked passively by some background event reactor. Basically, by iterating over an array of futures in application code, you're sort of "re-implementing" a poll event reactor at a higher level.
One straightforward use case for futures I've found is any situation where you have one or more async calls, and you can interleave some CPU cycles between calls. Suppose you have to call an HTTP web service twice, but the result of the first call gives you the opportunity to start processing immediately without the need to wait for the second call to complete. Futures make this easy, because you can just say:
future result1 = some_remote_call(); object data = result1.get(); // wait for result1 to complete future result2 = another_remote_call(); // ... do some processing here while we're still waiting on result2 ... //
So that's definitely a nice use case, but the more common case of waiting for N events to occur seems better suited for callbacks, despite the code-indirection we suffer using callbacks.
So, what are some well-known usage patterns/use-cases where futures provide a clear advantage (in terms of code readability and ease of implementation) over callbacks?