v146 · Web APIs · Navigation API
Navigation API: post-commit handler from precommit
Chrome 146 lets you register a post-commit handler from within a precommit (navigate event) intercept. A precommit handler runs before the URL changes; the post-commit handler registered inside it runs after the commit. This gives fine-grained control over tasks that must split across the navigation boundary.
concepts
-
Post-Commit Demo
Intercept a navigation with a precommit handler and register a post-commit handler from inside it. The log shows the timing: precommit → URL changes → post-commit → finish. Demonstrates the ordering guarantee.
-
Precommit vs Post-Commit
Side-by-side: what's available before commit (old URL still active) vs after commit (new URL in the address bar). Shows which tasks belong in each phase — e.g. start loading spinner in precommit, update page state in post-commit.
-
Intercept and restore
Pit the new precommit/post-commit shape against classic intercept under a flaky fetch. Side-by-side events & address-bar trace show which strategy keeps the URL committed and which rolls back.
-
SPA Router
A simulated SPA router that intercepts navigations with a precommit handler (starts the loading bar), registers a post-commit handler (renders page content once the URL commits), and logs every phase in a live timeline.
why it shipped
SPA navigation orchestration often needs to run code both before and after the URL commits. Before this API, the only way to split work across the commit boundary was awkward — you'd have to use the navigate event for precommit work and then rely on navigatesuccess for post-commit work, which couldn't share context with the precommit handler easily. Chrome 146 lets precommit handlers register a post-commit callback via event.intercept({ handler: async () => { /* runs after commit */ } }), keeping related logic co-located.
the API
navigation.addEventListener('navigate', event => {
if (!event.canIntercept) return;
// Intercept: handler runs AFTER the URL commits
event.intercept({
// commit: 'after-transition' (default) or 'immediate'
commit: 'after-transition',
handler: async () => {
// This runs AFTER the navigation URL has committed
// (new URL is in the address bar)
console.log('post-commit:', location.href);
await loadPageContent();
},
});
// Or use the shorthand to schedule code before and after:
event.intercept({
async handler() {
// Chrome 146: use event.signal.reason to distinguish phases
startLoadingSpinner(); // runs immediately (precommit)
await fetchNewContent(); // awaited in post-commit phase
stopLoadingSpinner();
}
});
});