refactor(router): add support for blocking router resources - #70293
refactor(router): add support for blocking router resources#70293atscott wants to merge 2 commits into
Conversation
d685fd5 to
08c24b3
Compare
Extends router resource integration to support blocking resources during navigation transitions. Resources declared in a route's `resources` function are blocking by default unless explicitly marked with `nonBlocking()`. Key behaviors include: - During the navigation transition, the router awaits the resolution of all blocking resources across target routes before proceeding to activation and completing navigation. - Blocking status is tracked via an effect on the underlying resource: if the resource settles with a value, the promise resolves; if the resource status becomes 'error', the promise rejects with the resource error, cancelling navigation and emitting `NavigationError`. - If a reused route is re-navigated to after a resource has errored (e.g., with `onSameUrlNavigation: 'reload'`), the router triggers `.reload()` on the underlying resource to retry the failed fetch. - All tracking effects are cleaned up upon resolution, rejection, or route injector destruction. - Supports both sync and async `resources` functions (returning `Promise<ResourceResult>`) as well as `rxResource`.
08c24b3 to
93857a5
Compare
|
|
||
| return Promise.all(resourceSetupPromises); | ||
| // TODO: wait for blocking resources | ||
| return Promise.all(resourceSetupPromises).then(() => Promise.all(blockingResourcePromises)); |
There was a problem hiding this comment.
Do we need all setup promises to resolve before we await the blocking resource promises? Can't we just await them all?
return Promise.all([...resourceSetupPromises, ...blockingResourcePromises]);There was a problem hiding this comment.
I nearly made this mistake today when giving it a final look. We have to wait for setup promises because only once those are resolved do we add to the blockingResourcePromises array.
| // Wrapped snapshot should be frozen at 'initial' during recovery loading | ||
| expect(wrapped.value()).toBe('initial'); | ||
|
|
||
| // Resource receives value while isLoading() remains true and status is 'loading' |
There was a problem hiding this comment.
I don't completely follow this, why would it still be loading if the resource is resolved?
There was a problem hiding this comment.
This came from feedback internally. They have a custom streaming resource that has this behavior. It has a value after it receives the first value but stays in the loading state until the underlying rxjs observable is marked completed.
| expect(resourceRef.value()).toBe('rx loaded 123'); | ||
| }); | ||
|
|
||
| it('should unblock navigation when a resource emits a value even while remaining in loading state', async () => { |
There was a problem hiding this comment.
I think this is the same use case I was confused about in the other test. Why does it remain loading?
b8fabc9 to
fab0f26
Compare
Extends router resource integration to support blocking resources during navigation transitions.
Resources declared in a route's
resourcesfunction are blocking by default unless explicitly marked withnonBlocking(). Key behaviors include:NavigationError.onSameUrlNavigation: 'reload'), the router triggers.reload()on the underlying resource to retry the failed fetch.resourcesfunctions (returningPromise<ResourceResult>) as well asrxResource.