For example, very rarely in my experience does a function switch between synchronous and asynchronous. So when it does happen and I have to update upstream call sites, it's not so frequent nor painful enough to damn the whole abstraction and then go "see? it sucks".
When people suggest an alternative abstraction like Go, I compare my 50 lines of WaitGroup code in Go to things like `await Promise.all([prom1, prom2])` in Javascript. It's all just trade-offs.
Take a look at Java's approach (Loom + Futures + Structured Concurrency). It allows you to be succinct yet avoid the explicit async/await approach.
2. We already have a way of making things run in parallel: threads and processes.
See the first code example in the fine article. The OS
Also, async/await doesn't cut you off from anything. You just need to understand what is and isn't an asynchronousable end-point, people get confused then start throwing random keywords around without really grasping how it works (e.g. "if I await everything, it is concurrent, right?!" then write a bunch of code that actually runs synchronously but with tons of overhead).
I guess this is my nice way of saying: You need to read this very article. It corrects your concerns, and shows you when async/await is useful and likely when it isn't.
Good: Rust, JavaScript/TypeScript, C# and Swift
Interesting: Golang, Erlang/Elixir
Bad: Java and most JVM implementations, C++ (cumbersome, the language is bad by modern standards in general)