In my experience, that kind of difference boils down to a combination of three things.
- Comparing apples and oranges. For example, Box makes pinning trivial (you can just move in and out of Pin no problem), but oftentimes people new to Rust try to prematurely optimise and eliminate a single pointer lookup. If that's the case, were you really writing the same thing in JS and in Rust?
- An extension to the previous point, the behaviour is usually different. What would happen in your JS implementation if two streams were awaited concurrently, one received a message, and the other had to be cancelled? What if one threw an exception? In Rust, you're forced to think about those things from the start. In JS, you're coding the happy path.
- Trying to reproduce the exact same architecture even if it's awkward of inefficient. For example, it's really really easy to use a stream wrapper [1] to produce a stream from a channel, but then the architecture gets very different.
> Again I needed to produce an async stream, and thats impossible using async fn
I strongly recommend a channel instead. There's also async_stream [2], but channels are simpler and cleaner.
Over two years of writing embedded, web, and CLI rust I didn't have to write a raw future once.
[1] https://docs.rs/tokio-stream/latest/tokio_stream/wrappers/in...