Web backends tend to have lots of concurrent connections doing IO-bound things. Processes or OS threads have too much overhead for this; they're more for when you want CPU parallelism with some communication between threads. Thread pools are still only a compromise. So JS with event loops made a lot of sense.
Greenthreading like in Golang is even better cause you get the advantages of OS threads, but that requires a runtime, which is why Rust didn't do that. And I guess it's hard to implement, cause Java didn't have it until very recently.
An early Java version had greenthreads, but they were soon removed in like the year 2000. That's pretty much the reason all our Java code at work uses some kind of cooperative multitasking with that painful promises syntax (foo().then(...))
Greenthreading like in Golang is even better cause you get the advantages of OS threads, but that requires a runtime, which is why Rust didn't do that. And I guess it's hard to implement, cause Java didn't have it until very recently.