-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Idea: Assimilate Native Promises Without Waiting #2
Comments
Technically we could also implement full shortening through assimilation, which would detect promise cycles enforced by the spec. |
Are there observable differences other than the number of ticks before certain tasks occur? I'm not seeing why there would be, offhand. |
The ordering of unresolved, forked promises can change: var resolveA;
var a = new Promise((r) => {
resolveA = r;
});
var resolveB;
var b = new Promise((r) => {
resolveB = r;
});
a.then(() => console.log('first'));
b.then(() => console.log('second'));
resolveA(b); // A now depends on B's settling.
b.then(() => console.log('third'));
resolveB(); // B becomes settled. With the ES2022 spec (and the proposed removal of the
This is because A forms a chain on top of B once
With assimilation, it now logs:
This is because A offloads it's chained reactions to B once
|
Are there libraries that we know of that depend on the specific, relative ordering of Promise resolutions like that? I want to believe that libraries 'should' treat Promise settles as something that happens in a future micro tick without having strong opinions about how should have elapsed or what the order should be relative to other micro tasks. That's probably naive so I wonder if there are concrete examples of this sort of implicit dependency in the wild. |
Probably not libraries, but I've seen tests that fail if you remove a |
There are two techniques to fulfilling a promise with another promise:
Promise adoption works through the public
then
API. Essentially, we callinner.then()
and pass it asettleOuter
function that will update the state of the outer promise with whatever it receives:The approach that I presented just eliminates the first tick. We still call
inner.then()
, and thatthen
will still wait a tick before calling outsettleOuter
function, and we still wait a tick before the outer chainedlog
happens. So the log happens during tick 2 at the earliest:Promise assimilation can eliminate 2 ticks. Essentially, it finds that the inner promise is a native promise, and it inspects its current state. If it's fulfilled, then we steal the fulfilled value. If it's rejected, we steal the rejection reason. And if it's pending, we forward our reactions to the inner promise so that they're fired as soon as the inner promise settles (instead of having the inner settle the outer, then firing after the outer settles).
If the inner is fulfilled/rejected, the outer promise is immediately settled and the log can happen at tick 1. If the inner is pending, then we're able to fire the chained log the tick after the inner finally settles. Either way, it happens 1 tick earlier than what's possible through promise adoption.
This does have some observable differences if you chain fork a promise into multiple reactions, but this isn't super common. Most promises are straight
.then().then().then()
, and they'll only run through their straight chain faster.The text was updated successfully, but these errors were encountered: