-
Notifications
You must be signed in to change notification settings - Fork 45
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
Yieldy API Naming #95
Comments
@noamr to keep me honest on the LoAF bits. |
This is a great summary, and I agree with your points carefully laid out--- yet I don't love the outcome. +1 to
With the naming of LoAF it was explicitly prefixed with Animation Frame to differentiate all the different types of "frames" that might be associated by developers (it was initially called "Long Frames" and was renamed). Most developers will not think of "animation frames" first and foremost when seeing unqualified "frames" (though I only have a few anecdotes to form this opinion), even when in the context of scheduling it is the only one that makes sense.
The biggest issues is that I still think it doesn't solve the problem you highlighted: is it before, during, or after? I know what is being implied by What about something like Finally,
If the feedback was primarily about On the other hand, one other concern with Ideas for alternatives:
(For what it's worth, various GPTs both stack ranked |
I also liked How about:
|
Yield:
+1. I thought alternatives were worth exploring, but I think
I had considered this a while back, and:
The "tick" idea is interesting, but I'd be wary of introducing that concept into HTML since I'm not sure how well it maps to HTML concepts. For example:
Wait/timeout:
I don't mind Render: What about folding this into
OTOH, I'd rather keep
What other properties would To summarize, what about:
Thoughts? |
I like this direction. Though are we OK with |
The main one I was expecting was a property to represent
Fair enough-- it's not strictly needed for scheduling, but developers seem to desire a promise based rAF() alongside promise based setTimeout() and I thought... give the people what they want ;) I think Earlier in the thread you suggested the name
Question: if I had (I also wonder when the continuation would get scheduled if e.g. tab goes to background and rendering is throttled, which is a problem with rAF based scheduling) |
Maybe a non-boolean parameter would be easier to feature detect, e.g. passing an invalid enum value should throw? I like the direction of your offline suggestion of
Yep, that's what I was thinking. I think the pros outweigh the cons, and it's easy enough to wrap in a
Yeah you could use
The plan is to ensure pending
I wonder if this behavior would obviate the need for doing the scheduler after-render unless 100 ms thing? |
Another possibility for timeouts: dwell. It comes from electronics.
I think it works for both time and the rendered condition. await scheduler.yield() // I want to run now but I'm politely yielding
await scheduler.dwell(1_000) // Let me dwell here for 1 second
await scheduler.dwell('rendered') // Let me dwell here until the next render is done They're both imperative verbs. They're similarly short. It's unfamiliar but I think the meaning is sufficiently clear that devs will understand it easily. It also gives a nice place for future expansion to new "dwell until" conditions, a desire mentioned in other threads. Some definitions from wiktionary.
|
I'm not sure I love However, I did want to point out that we didn't consider the Maybe any feature that is okay to delay for rendering is also okay to continue being scheduled at non-continuation priority? |
I forgot to say: I'll dwell on it for a bit :) |
My personal perspective here is that If anything, a single await scheduler.wait(); // Until the next available task.
await scheduler.wait(100); // Wait for at least 100 milliseconds.
await scheduler.wait({ time: 100 }); // ... a more verbose version of the previous. I have real problems with await scheduler.wait({animationFrame: true}); // Wait for the next animation frame.
await scheduler.wait({waitForRender: true}); // or this, but why does it say wait twice?
await scheduler.wait({render: 'end'}) // or this. But this could get a little out of hand.
To avoid that explosion, I think you have to regard the scheduler is a useful primitive that underlies a bunch of other stuff that the platform does. Though all events and callbacks logically need to pass through the scheduler, the scheduler itself is rarely the direct target of calls. await scheduler.wait({fetch: fetch("https://example.com")}); // This is madness.
await fetch("https://example.com"); // This is how most APIs will be used instead. So while there might be a few core things that are exposed directly, most stuff that uses the scheduler won't need to involve the So, when it comes to I'm wondering whether a fix for the rendering piece could be deferred. p.s., I prefer |
I'm not a big fan of these boolean dictionaries, perhaps await scheduler.wait({for: "render"}) ? |
@noamr, You'll note that my comment goes on a little from that point, where I used those examples to illustrate how things were not necessarily headed in a good direction. Also, isn't "for" a reserved word in JS? I'd hate to have to quote it all the time. |
Fair enough, I was bikeshedding instead of responding to the point. The thing with Reading what you said, I'm not sure the In addition, not sure if Perhaps we could have this as independent promise getters in the global object, where await globalThis.afterCurrentTask;
await globalThis.timeout(3000);
await window.afterNextAnimationFrame;
Can be |
Pretty sure reserved keywords don't impact what you can write there. |
Why would render() belong to window only? |
Right! Forgot about offscreen canvas. |
What if it were just a string? await scheduler.wait('rendered') Then you have numbers for a delay, and strings that name a handful of core conditions. await scheduler.wait(500) // Wait half a second
await scheduler.wait('frame') // Wait until the next frame, without forcing one
await scheduler.wait('rendered') // Wait until next render is done
Re node, it's something I'd like to use. My server that runs tasks has things with different priorities that should be scheduled differently. Sometimes priorities change and the scheduling should follow that. I want a big website spider that will run for several weeks to be
Current ethos seems to hate this pattern, but I love it. It feels good to use generated promises. But, Still, it is so tempting. It would look like this with current signal propagation. // Adopts current priority
// Follows priority changes of requesting task
await scheduler.frame // Wait until next frame
await scheduler.rendered // Wait until next render is done |
Or it could take a single, non-optional argument that could be either a number or enum, and the promises could be combined with
The main differences are that a built-in API wouldn't need to schedule rendering (as @noamr mentioned), so there's a potential performance benefit from not having to wait and not running the rendering machinery if not needed. And it could take into consideration visibility (current and changing), which a polyfill could as well, but it makes it more complex. Aside from the "yield and don't block rendering" use case, we're also interested in exploring a way to indicate that "rendering now would be ideal." How browsers schedule and yield-from-tasks for rendering is complex, and providing a signal could help augment heuristics (e.g. parsing). For example, some sites have a good idea of where above-the-fold content ends, and inserting a signal indicating a request for rendering could be helpful in optimizing page load. I'm interested in exploring if this would be beneficial, although I'm not sure what the best way to expose this is (the imperative |
As pointed out in WebKit/standards-positions#361,
scheduler.render()
is inconsistently named with.wait()
and.yield()
because the method doesn't actually render.Some additional concerns that came up in discussion:
.wait()
(as well as.waitForRender()
) is a bit awkward withawait
, and that will probably be more common then.wait().then(...)
(which does read well).render()
is ambiguous: is the promise resolved before, during, or after rendering?Trying to alleviate all of these concerns is tricky, but here's an attempt:
.wait()
:.timeout()
represents what you're waiting for, and it's in line with bothsetTimeout()
andAbortSignal.timeout()
..yield()
: If.wait()
becomes.timeout()
, this should be a noun too (per (3)). The promise returned by.yield()
represents a continuation of the current task, and awaiting a continuation is yielding, so.continuation()
seems natural. I'm a little worried that.continuation()
will be less intuitive for developers than.yield()
, but maybe that's a documentation problem?.render()
: This is tricky because "rendering" is both the relevant noun ("update the rendering") and verb ("render"), which makesawait scheduler.rendering()
awkward and ambiguous. I chose.nextFrame()
because I think it aligns with the LoAF processing model: in LoAF, the frame timing is reset after the task if no documents need rendering, or after rendering if they do. That matches the the intended behavior of the promise resolution for this API.The text was updated successfully, but these errors were encountered: