-
Notifications
You must be signed in to change notification settings - Fork 28
Description
The design of navigation interception, especially after #46 lands, leads to a novel situation. Namely, you can perform a single-page app navigation which fails, by passing a rejected promise to event.respondWith(). A somewhat-realistic example might be:
appHistory.addEventListener("navigate", e => {
e.respondWith((async () => {
const response = await fetch("https://nonexistant.invalid/some-data.json");
// ... etc ...
})());
});
// This will get intercepted and converted to a failure.
location.href = "/foo";The current plan as of #46 is that, because of the issues discussed in #19, all such navigations will synchronously succeed, but then asynchronously fail. Roughly:
location.href, the URL bar, etc. immediately start pointing to/foo, as if you'd donehistory.pushState(null, null, "/foo").appHistory.current, as well as the underlying session history model, gets pointed to a new history entry for/foo.- Any forward history entries get thrown away.
- But then, once the browser sees that the promise is rejected, it "rolls back" the navigation:
- It sets
location.href, the URL bar, etc. back to the original URL that initiated the navigation. appHistory.current, as well as the previous session history model, navigates back to the previous session history entry.- The history entry for
/foocreated in step (2) gets thrown away. - The forward history entries thrown away in (3) remain dead.
- It sets
Is this the right model for when the navigate handler tells us the navigation failed?
The main alternative, I think, is to do a lot less. I.e., do not try to provide a rollback; leave location.href, the URL bar, etc. on /foo. Instead just signal to the app (e.g. with an event on window.appHistory and/or window.appHistory.current) that the promise rejected, and have the app handle that. The app could do its own rollback, perhaps. Or it could display a literal error page, like it might for a server-side 404.
I'm kind of leaning toward this do-less model. What do people think?
The other alternative would be to go the route of (2) in #19 (comment), which would allow us to delay all the updating stuff until we're sure the promise fulfills. Then there would be no navigate-then-rollback; we'd just never move at all in a failure case.