Cooperative multitasking will always have the blocking problem, whether implemented manually or by the language. The manual callback chaining is tedious, though.
Preemptive multitasking solves that problem, but if mixed with lots of shared mutable state, it reintroduces much worse problems of non-determinism and unreproducible bugs.
The golden path involves preemptive multitasking with little-to-no shared state. That way you get to have your cake (determinism) and eat it too (no blocking problems/starvation).