Re:Idle Until Urgent
by paulddraper on Thursday September 20, 2018 @05:43PM
(#18035703)
My initial point what that your terms are muddled.
Your hypothetical could benefit from a preemptable (aka non-cooperative) scheduler, which can forcibly interrupt A, to allow C to start.
A cooperative scheduler (which is what JS has) is at the mercy of A to properly yield.
---
As for how to yield on the macro- or microtask queue of your choice, they are the same difficulty to write.
// HTML5, Node.js
await new Promise(resolve => resolve());
await new Promise(resolve => setTimeout(resolve, 0));
// Node.js
await new Promise(resolve => resolve());
await new Promise(setImmediate);
You're correct that setTimeout and setImmediate are not guaranteed to work on all ES runtimes, because they are HTML5 and Node.js specific additions. (As is the entire concept of a separate macrotask queue, which you dislike so much.)
The question is how would you make sure 4 happens before 2?
Here's a real world example, from Node: You need to make 3 service calls, A B & C, to build a page. Service A is the fastest call, but takes a lot of processing time. Service C is the slowest call, but requires a bit of data from Service B. Since A and B are unrelated, odds are good they're being invoked from completely separate parts of the code.
If you fire A and B, service C won't get called until service A's processing is complete. You could await both A and B, then call C before you start the processing, but you have to turn your code flow inside out to do that, so it only works for trivial applications.
Adding promise chaining to A.process() won't get B's promise to resolve before A's chain finishes resolving. setImmediate() might work in some places, and you might be able to come up with a code pattern that works for your team, but I don't believe it's guaranteed to work everywhere.