Skip to content
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

Allow waiting for pending traversals before committing new push #252

Open
tbondwilkinson opened this issue Oct 28, 2022 · 1 comment
Open

Comments

@tbondwilkinson
Copy link
Contributor

Here is an example of something we do in our applications:

navigation.addEventListener('navigate', (e) => {
  e.intercept({handler: () => Promise.resolve()});
});
const key = navigation.currentEntry.key;
navigation.navigate('/foo');
navigation.traverseTo(key);
navigation.navigate('/bar');

A concrete example of this is:

  1. View A (say, a modal) adds a history entry, '/foo' when it opens.
  2. View A closes, due to user activation, and the result of that user activation is to synchronously close the modal.
  3. View B (say, another modal, but maybe not) opens, synchronously due to the same user activation, but in code after the effects of (2), and adds a history entry, '/bar' when it opens.

The resulting history, based on the above is [/, /foo, /bar] with the current URL being / rather than what the code might expect, as [/, /bar] with the current URL being /bar.

The reason for this is that navigate requests synchronously resolve, regardless of existing traversal requests.

For traversals, the navigation event and the transition property are called and populated asynchronously. Meaning that immediately after a call to navigation.traverseTo we have no ability to detect that a traversal is occurring and we might want to wait for it to commit (or cancel).

We work around this issue in the existing API only partially, but essentially if a user requests a traversal in JS, we wait for the next popstate to ensure that the traversal has resolved before we allow further requests to the browser to change history. So, we queue up push navigations until ready.

Proposed resolution:

My proposal is:

  1. Synchronously expose information about pending traversals so that the router can choose whether to wait for or cancel existing traversals.
  2. In conjunction with Will the current transitionWhile() design of updating the URL/history entry immediately meet web developer needs? #66, enable deferring the commit for a navigation until the pending traversals have finished.

This would move the code that currently has to wait for existing traversals before navigate() can be called into the navigate handler, which would catch any and all calls to navigate.traverseTo and history.back.

@domenic
Copy link
Collaborator

domenic commented Oct 31, 2022

So, the intention here was that you would write such code as

await navigation.navigate('/foo').finished;
await navigation.traverseTo(key).finished;
await navigation.navigate('/bar').finished;

I'm guessing that's not an option in your case, e.g. because the third line is located somewhere else in the codebase where the return value of navigation.traverseTo() is not easy to access.

And indeed, it sure seems like navigation.transition was intended to be helpful here. Then the code could look something like

await navigation.transition.finished;
navigation.navigate('/foo');

await navigation.transition.finished;
navigation.traverseTo(key);

await navigation.transition.finished;
navigation.navigate('/bar');

which is nice and easy to divvy up into multiple disconnected files. And indeed, if we work on #66, you could add the await navigation.transition.finished inside the navigate handler, so that your original code works as-is with no workarounds.

So I think this is a matter of ensuring we populate navigation.transition the moment a traversal is requested, instead of the moment it actually starts. That seems reasonable to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants