As for the “complexity”, I largely solved this problem by limiting dimensionality of stream handling to 1, and chaining streams via explicit function calls so that I was never map/flat mapping stream to stream to stream etc.
This made everything much easier to understand in my projects, and also test etc.
But you’re right as now that async/await is in Swift proper I’m not sure it makes much sense anymore. There’s still some functionality I need that seems external (looks like async sequence might help once I can use iOS16 as a min spec?). Beyond the basic stuff, it’s essential that I can:
1) Define explicit timeouts that throw typed errors for every step of the async process
2) Have the ability to queue up an array of async operations (each with their own timeouts), dispatch them in a serial queue, then buffer their results to emit a single array, itself with a global timeout
3) While doing all of the above, I need a way to terminate async actions “in flight” upon receipt of some signal, so that a long running async queue can be aborted if necessary
Once all of the above is possible I’ll probably go back and rip out Rx (Combine) in a few years for a pure async-await implementation, but that will take forever