For most asynchronous IO operations, the old standby of threads works an absolute treat. There are certain pathological corner cases where a single thread can be blocked, but for the other 99.9% of use cases, it works fantastically.
Build your synchronous and stateless web code and throw it into a thread. Done. Even the more complex cases of a single worker needing to make multiple asynchronous calls can be handled easily without even having to leave the standard library.
Now then, this falls apart a bit when you have to deal with global state (and the assorted locks and deadlocks), but most web backends aren't too hard to write statelessly.