-
Notifications
You must be signed in to change notification settings - Fork 26
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
How to detect or await a pending navigation if you didn't initiate it? #11
Comments
I do think that this type of coordination code should be done by the application itself- which assumedly has a navigation handler itself, and has probably some type of router that's installed via that route. So, the router knows about all pending navigations, and if some part of the application needs to also know, it should ask the router. Figuring out how this works on pages where some piece of logic CANNOT talk to the central router feels out of scope, and is a case we've punted on in other categories as well. |
@tbondwilkinson I don't think it's reasonable to require a central router abstraction over top of the platform in this case. That's a major issue with the existing API surface of pushState() where ex. code that doesn't use react-router will break the app. I don't think it's reasonable to say that no part of the page can call pushNewEntry() directly, and instead app components must go through some router library. That's also antithetical to the concept of web components where you can have two unrelated frameworks on the page like React and Lit and your app will still work. |
Sorry, let me be more clear. I think that anyone can call I do agree there's still some work to be done to enable third-party code to work with history, which someone brought up in #18. I don't think that any app component needs to be aware of what the centralized router implementation is, and should be able to use the native framework itself to get all information and make navigation requests as necessary. But I also don't think that any part of the app component needs to be listening directly to ALL navigations when they only really care about a portion of the URL or a portion of the history state. |
#68 attempts to address many of the surrounding issues around queued-up navigations, by getting rid of them: new navigations interrupt ongoing ones. However, the essential problem this issue gets at in its OP still remains, which is: what if I want to wait on an ongoing navigation? How do I do that? You can do so in the post-#68 explainer by listening for the appHistory.nextOrOngoingNavigation.then(theNavigationSucceeded, theNavigationFailed) where What do folks think? Suggestions for a better name are very appreciated as well. |
More for curiosity's sake: is there a reason that that said, I also do like the ergonomics of the promise. |
They don't have to be different, but it fits with other web platform patterns: e.g. onload and onerror pairs all over the place. |
The one wrinkle in this is that I want to make sure this works: while (appHistory.nextOrOngoingNavigation) {
await appHistory.nextOrOngoingNavigation;
}
appHistory.push(url) That is, someone else might beat you to initiating a navigation, so if that's the case, the Promise should synchronously exist. If we don't want the |
Very interesting example. This would be the first nullable promise on the web platform if we went that route. (In fact Web IDL does not currently allow nullable promises, but I suspect that was based on thinking of them mostly as inputs...) I kind of like the idea of making it nullable, though... then its name could just be However, if we kept the non-nullable "next-or-ongoing" semantics, then you could do while (!appHistory.current.finished) {
await appHistory.nextOrOngoingNavigation;
}
appHistory.push(url); Hmm, maybe that suggests a different bikeshed color? while (!appHistory.current.finished) {
await appHistory.current.whenFinished;
}
appHistory.push(url); This latter is kind of nice because then we don't have the replacing-itself promise; each entry just gets its own promise, which once settled, never changes. (Although, it's a bit strange for both |
or this is another option, but doesn't have that promise-based interaction you're looking for. if(!appHistory.current.finished) {
appHistory.current.onfinish = () => {
appHistory.push(url)
})
} |
This gives insight into any "ongoing" navigation, i.e. a navigation that hasn't yet reached navigationsuccess/navigationerror because the promise passed to respondWith() has not yet settled. Additionally: * Removes the finished property from every AppHistoryEntry, which is nice because it only ever really made sense on the current entry; it was about the transition. Instead, the presence or nullness of appHistory.transition can be used. * Adds a type property to AppHistoryNavigateEvent since we're going to have it on appHistory.transition anyway so having it earlier (before respondWith() is called) seems very reasonable. Closes #86. Closes #11 by adding the appHistory.transition.finished promise. Helps with #41 as you can retrieve data from the replaced entry, at least during the transition, with appHistory.transition.previous. Probably helps with #14 (although currentchange needs a bit of an overhaul) since appHistory.transition has the sort of useful information discussed there, such as the previous entry or the type of navigation.
This gives insight into any "ongoing" navigation, i.e. a navigation that hasn't yet reached navigationsuccess/navigationerror because the promise passed to respondWith() has not yet settled. Additionally: * Removes the finished property from every AppHistoryEntry, which is nice because it only ever really made sense on the current entry; it was about the transition. Instead, the presence or nullness of appHistory.transition can be used. * Adds a type property to AppHistoryNavigateEvent since we're going to have it on appHistory.transition anyway so having it earlier (before respondWith() is called) seems very reasonable. Closes #86. Closes #11 by adding the appHistory.transition.finished promise. Helps with #41 as you can retrieve data from the replaced entry, at least during the transition, with appHistory.transition.from. Probably helps with #14 (although currentchange needs a bit of an overhaul) since appHistory.transition has the sort of useful information discussed there, such as the previous entry or the type of navigation.
For posterity, the way to do #11 (comment) in the current explainer is while (appHistory.transition) {
await appHistory.transition.finished;
}
appHistory.navigate(url); |
ex. Gmail uses a global queue, if there's a pending navigation it won't process any future requests to navigate until that's done. The opposite of the photo gallery example. If you click Next Page 20 times, nothing happens until the next page has loaded.
The text was updated successfully, but these errors were encountered: