It is, and not only to you. It is a way to save a call stack until a runloop calls it back.
But what I can’t agree with is parallels with OS. Coop MT is only problematic in OS MT. When it’s your code there’s no unknown bad actor, and having multiple cooperative (mostly waiting) processes without scheduling them on a thread pool is a useful concept regardless of threads availability.
E.g. when you have to wait on multiple sources, the options you have are:
- serialize
- perform few non-blocking calls and wait for any/all of them to complete
- schedule them as tasks on a thread pool and wait for their completion
Async can do all three, it’s orthogonal. I’d say that just awaiting on PMT task completion is much more convenient that setting up locking primitives. Same for NB polling. Promise is just an abstraction and all it does is waiting for an event to fire on a current thread’s runloop while retaining the comfort of a lexical scope, all with a couple of keywords.