-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Add document.ready
promise
#127
Comments
So what would the equivalent be for |
Is there any implementor interest, and have you done a search in existing content to see if many scripts already use |
There is definitely interest for this. Using promises for state transitions is much more developer friendly. |
Here's a discussion on this from last year https://lists.w3.org/Archives/Public/public-whatwg-archive/2014Mar/0091.html Completely agree. Anything with an onload/error event should get a |
(But I do think .ready should be dom ready) |
Do you mean that |
Yep, agree for the same reasons. We might want |
Yeah, it would bad if we ended up with some incomprehensible mix of |
A suggestion:
Because the window is ready when everything is loaded, but the One possible downside is that there are a lot of jQuery exemples out there with |
In general I feel that |
That fits with |
We already have |
There's also |
Images are also special. https://html.spec.whatwg.org/multipage/embedded-content.html#img-available Images can also have two requests going at the same time. The "pending" request is basically hidden currently, but there is some interest in exposing it. See ResponsiveImagesCG/picture-element#269 strawman proposal: var currentURL = img.currentURL;
var currentPromise = img.ready;
var pendingURL = img.pending.currentURL;
var pendingPromise = img.pending.ready; |
@zcorpan do we need a distinct object or is simply using |
No particular need for a distinct object. |
@zcorpan does that cover everything |
@annevk Yes. |
I'm a little stuck on ready vs. loaded now :(. The precedent of jQuery is ready = DOMContentLoaded. The precedent of FontFaceSet is ready = loadingdone (~= load). Is it possible for us to have a consistent story? Maybe one consistent story would be that suggested by @fvsch in #127 (comment): We could also omit or rename What do people think? |
Another consistent story would be ".ready means just do the right thing", and we say that that's DOMContentLoaded for documents (and windows?). That also jives with |
FontFace and FontFaceSet don't have any other comparable notion of "ready". I'm fine with it meaning "do the right thing" (tho of course we have to police new usages to make sure it really is the right thing). |
👍 we all need it for ... web-components revolution 😈 |
Yeah, the policy ".ready means just do the right thing" seems reasonable. If we could avoid a mix of |
|
"The right thing" does seem a tad hacky though and will likely change over time as more of the kernel gets exposed and programming patterns evolve. |
I still like @domenic's idea of Agree with @annevk on |
Yeah, I really do tend to agree with that. Having to remember which one to use per API seems like a bad WTFWeb experience that will get us mocked in blog posts and conference talks for years to come.
Right, that is the problem with that approach :(
Do you think we should have both {window,document}.{ready,subresourcesReady}? Or just pick one base object? If so which one?
I think this idea is only good if we can say there is always a .loaded so that web devs don't need to know about .ready in most cases, except maybe one special case of document/window which seems fine since it already has two 'loaded' events
I disagree with this. It puts the legacy API in control of naming. Part of the issue we're trying to solve here is making things uniform, so that people don't have to remember DOMContentLoaded vs. load vs. loadingdone vs. success vs. ...
That's an interesting idea. {window,document}.ready = load, {window,document}.domReady = DOMContentLoaded? |
I would just pick one object, probably |
I don't think we should make All questions about the promise reset processing model are easier to answer with concrete spec text, so I won't really spend time going over that here. |
I’m so happy to see movement on
If we’re saying Or, if we’re saying IMHO, the need for something like |
You don't have to use image.loaded if it isn't useful for your use cases. For the vast majority of images whose src does not ever change more than once (from empty to a URL), it will serve well. |
Some thoughts on the names for document's promises: This is a classic web-specs "goodness vs. consistency" tradeoff. I am siding with consistency with the existing spec concepts and names (interactive, content loaded, and loaded). The alternate world, where we go for good-but-inconsistent, is where we try to make up a nice set of names disconnected from the existing concepts. For example:
But in the end I think consistency is more valuable here. Telling people "parsed will fulfill when the document's readystate becomes interactive" or "ready means DOMContentLoaded" or "subresourcesLoaded means the load event fired" is just kind of WTF. Sticking with "interactive will fulfill when the document's readystate becomes interactive", "contentLoaded will fulfill when DOMContentLoaded fires", and "loaded will fulfill when the load event fires" is a much simpler story. This means we'll want to add a nice section to the spec explaining the difference between these three stages, since we won't be able to obviously infer them from their names. But I don't know if it was ever going to be that obvious, no matter what names we picked, and such sections are helpful anyway. |
This closes #127, although that thread also contains discussion about adding other "loaded" promises for various elements, which will move elsewhere. For a discussion of the names, including why jQuery's "ready" naming was not used, see #127 (comment).
The pull request for the document promises is up at #1936. I'd like to add 1-3 small web-developer-facing examples of when you would use them, but am not able to come up with any great ones myself that are not instead better served by <!-- in the head -->
<script>
const jsonPromise = fetch("some-data.json").then(r => r.json());
Promise.all([jsonPromise, document.interactive)]).then(([data]) => {
// use data to manipulate the guaranteed-to-be-parsed contents of the document
});
</script> and I guess you could say "in this example, substitute in contentLoaded if you only want to manipulate the document after crucial scripts have run, and use loaded for non-essential document manipulation that can happen after all subresources have loaded." What do people think of that? Do you have better scenarios? |
Ah, I see @jakearchibald has lots of nice examples at https://lists.w3.org/Archives/Public/public-whatwg-archive/2014Mar/0110.html, although they depend on the promises for links/images/etc. also being in place. Maybe it's best to hold off on examples until both are in the spec, and then we can use some of Jake's rather compelling and realistic examples. |
I have no memory of writing those. |
@domenic I like your example, but might be more readable as… fetch("some-data.json").then(r => r.json()).then(data => {
document.interactive.then(() => {
document.querySelectorAll(".username").textContent = data.username;
});
}); More nesting, but avoids the I dunno when it's acceptable to throw fetch("some-data.json").then(r => r.json()).then(async data => {
await document.interactive;
document.querySelectorAll(".username").textContent = data.username;
}); …reads well IMO. |
@jakearchibald I agree it's more readable indeed. Though It avoids the beginner's pitfall of making requests late instead of early (e.g. if two requests don't depend on each other, nesting would make the second request not start until after the first completes). If you swap Personally I've seen too much code simply wrapping everything in a document-ready handler when it would make so much sense to fire off certain requests earlier. But I don't know if this anti-pattern justifies changing simple cases when they are "the right way around". No strong preference one way or the other. Just thought I'd mention it. Perhaps removing the destructuring makes a good compromise? For what it's worth, this is a common case where I enjoy the guilty pleasure of variadic arguments in $.when(
$.ajax( .. ),
$.ready
).then(data => {
// ..
}); |
@Krinkle fwiw, I tackled this point over at https://developers.google.com/web/fundamentals/getting-started/primers/async-functions#careful_avoid_going_too_sequential |
Here’s a polyfill / prollyfill: https://github.com/jonathantneal/document-promises I’ve subscribed to the PR in case there are any changes before the merge. |
Please, please, please please rename the polyfill, using e.g. a _ or $ prefix. If people start using that code before it is implemented in browsers, we will need to rename them to avoid conflicts with the existing usages. |
Wouldn't checking that each property is nonexistent, instead of the single |
No; that's exactly the worst possible world, since then we can't change the semantics without also changing the name (since apps depend on the polyfill semantics, which aren't applied because something with different semantics but the same name appears). Let's take this discussion to jonathantneal/document-promises#4. I am fully prepared to withdraw this proposal unless we can get these polyfills renamed or turned into a library that doesn't squat on global names, ASAP. |
Related to jonathantneal/document-promises#4, ponyfill changes were reviewed by @domenic, and then merged and published. You may proceed with the bettering of the internet. |
This closes #127, although that thread also contains discussion about adding other "loaded" promises for various elements, which will move elsewhere. For a discussion of the names, including why jQuery's "ready" naming was not used, see #127 (comment).
How will these promises reflect on Navigation Timing? Right now it has two of these related events as part of its timing model to ensure the event processing is not wrongly attributed to the event before or after it.
This means that code running in a DOMContentLoaded event handler or I'm curious when the promise handlers would run. Also with regards to promises being async (though not sure if that matters given they're micro tasks?). Actually, I'm also curious how the current My main concern is ensuring that:
|
It's annoying to deal with
window.onload
, since your async code might not know whether it's run before or after the load event has fired. jQuery makes this easy with its$.ready()
function, which functions in a promise-like manner.So anyway, let's add a
.ready
promise toDocument
.The text was updated successfully, but these errors were encountered: