40 ms·
The distinction between this and the coroutine-esqe approach provided by something like Quasar (linked in a sibling comment) is that even with the best of futur
by heavenlyhash 12y ago
The distinction between this and the coroutine-esqe approach provided by something like Quasar (linked in a sibling comment) is that even with the best of future/promise APIs, the callbacks/futures/promises paradigm of code is still... viral. Inverting the flow of one region of a project to bounce callbacks/futures/promises solves problems there, but when it's exposed at the end as a future/promise, now your calling code has two choices:
- Block a thread again on that promise
- Keep chaining out more promises
The former choice works, but limits scalability just like the poorly parallelized code we're trying to escape from. The latter choice is infectious: it keeps pushing the inversion of flow and scheduling concerns farther and farther out.
Using Quasar's fibers to call code that's "blocking" (but secretly just jumps back into use via the scheduler) scales the same way async callbacks do -- threads are always doing real work instead of blocking -- but it doesn't have the "viral" problem. When you take a stacktrace, it's exactly the same as your old blocking code: it's an actual record of how you got here! Callback based code invariably loses that feature of stacktraces, no matter how fine of an implementation of future/promise patterns is wrapped around it.
Incidentally, lest this read as a pitch for Quasar in particular, I should mention that this entire comment could all be regex'd into a pitch for Golang's goroutines and scheduler. Quasar is just the only good implementation of it for the JVM I'm currently aware of. (Other libraries have implemented some of the backing components, like Apache JavaFlow as long ago as 2006, but I experimented with it once and found it to be a far cry from the high-level APIs I actually want to use.)