Skip to content

Commit

Permalink
refactor(router): refactor and simplify router RxJS chains (#40290)
Browse files Browse the repository at this point in the history
Refactor and simplifiy RxJS usage in the router package
in order to reduce its size and increase performance.

PR Close #40290
  • Loading branch information
martinsik authored and atscott committed Jan 11, 2021
1 parent 4a7a649 commit 9105005
Show file tree
Hide file tree
Showing 11 changed files with 70 additions and 105 deletions.
2 changes: 1 addition & 1 deletion goldens/size-tracking/integration-payloads.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,4 @@
}
}
}
}
}
12 changes: 0 additions & 12 deletions packages/core/test/bundling/router/bundle.golden_symbols.json
Original file line number Diff line number Diff line change
Expand Up @@ -1238,12 +1238,6 @@
{
"name": "findPath"
},
{
"name": "fireActivationStart"
},
{
"name": "fireChildActivationStart"
},
{
"name": "first"
},
Expand Down Expand Up @@ -1832,12 +1826,6 @@
{
"name": "routerNgProbeToken"
},
{
"name": "runCanActivate"
},
{
"name": "runCanActivateChild"
},
{
"name": "rxSubscriber"
},
Expand Down
10 changes: 4 additions & 6 deletions packages/router/src/directives/router_link_active.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,10 @@ export class RouterLinkActive implements OnChanges, OnDestroy, AfterContentInit
/** @nodoc */
ngAfterContentInit(): void {
// `of(null)` is used to force subscribe body to execute once immediately (like `startWith`).
from([this.links.changes, this.linksWithHrefs.changes, of(null)])
.pipe(mergeAll())
.subscribe(_ => {
this.update();
this.subscribeToEachLinkOnChanges();
});
of(this.links.changes, this.linksWithHrefs.changes, of(null)).pipe(mergeAll()).subscribe(_ => {
this.update();
this.subscribeToEachLinkOnChanges();
});
}

private subscribeToEachLinkOnChanges() {
Expand Down
10 changes: 4 additions & 6 deletions packages/router/src/operators/apply_redirects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import {Injector} from '@angular/core';
import {MonoTypeOperatorFunction, Observable} from 'rxjs';
import {MonoTypeOperatorFunction} from 'rxjs';
import {map, switchMap} from 'rxjs/operators';

import {applyRedirects as applyRedirectsFn} from '../apply_redirects';
Expand All @@ -19,9 +19,7 @@ import {UrlSerializer} from '../url_tree';
export function applyRedirects(
moduleInjector: Injector, configLoader: RouterConfigLoader, urlSerializer: UrlSerializer,
config: Routes): MonoTypeOperatorFunction<NavigationTransition> {
return function(source: Observable<NavigationTransition>) {
return source.pipe(switchMap(
t => applyRedirectsFn(moduleInjector, configLoader, urlSerializer, t.extractedUrl, config)
.pipe(map(urlAfterRedirects => ({...t, urlAfterRedirects})))));
};
return switchMap(
t => applyRedirectsFn(moduleInjector, configLoader, urlSerializer, t.extractedUrl, config)
.pipe(map(urlAfterRedirects => ({...t, urlAfterRedirects}))));
}
52 changes: 23 additions & 29 deletions packages/router/src/operators/check_guards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
*/

import {Injector} from '@angular/core';
import {defer, from, MonoTypeOperatorFunction, Observable, of} from 'rxjs';
import {concatAll, concatMap, first, map, mergeMap} from 'rxjs/operators';
import {concat, defer, from, MonoTypeOperatorFunction, Observable, of} from 'rxjs';
import {concatMap, first, map, mergeMap} from 'rxjs/operators';

import {ActivationStart, ChildActivationStart, Event} from '../events';
import {CanActivateChildFn, CanActivateFn, CanDeactivateFn} from '../interfaces';
Expand All @@ -23,25 +23,23 @@ import {prioritizedGuardValue} from './prioritized_guard_value';

export function checkGuards(moduleInjector: Injector, forwardEvent?: (evt: Event) => void):
MonoTypeOperatorFunction<NavigationTransition> {
return function(source: Observable<NavigationTransition>) {
return source.pipe(mergeMap(t => {
const {targetSnapshot, currentSnapshot, guards: {canActivateChecks, canDeactivateChecks}} = t;
if (canDeactivateChecks.length === 0 && canActivateChecks.length === 0) {
return of({...t, guardsResult: true});
}
return mergeMap(t => {
const {targetSnapshot, currentSnapshot, guards: {canActivateChecks, canDeactivateChecks}} = t;
if (canDeactivateChecks.length === 0 && canActivateChecks.length === 0) {
return of({...t, guardsResult: true});
}

return runCanDeactivateChecks(
canDeactivateChecks, targetSnapshot!, currentSnapshot, moduleInjector)
.pipe(
mergeMap(canDeactivate => {
return canDeactivate && isBoolean(canDeactivate) ?
runCanActivateChecks(
targetSnapshot!, canActivateChecks, moduleInjector, forwardEvent) :
of(canDeactivate);
}),
map(guardsResult => ({...t, guardsResult})));
}));
};
return runCanDeactivateChecks(
canDeactivateChecks, targetSnapshot!, currentSnapshot, moduleInjector)
.pipe(
mergeMap(canDeactivate => {
return canDeactivate && isBoolean(canDeactivate) ?
runCanActivateChecks(
targetSnapshot!, canActivateChecks, moduleInjector, forwardEvent) :
of(canDeactivate);
}),
map(guardsResult => ({...t, guardsResult})));
});
}

function runCanDeactivateChecks(
Expand All @@ -61,15 +59,11 @@ function runCanActivateChecks(
forwardEvent?: (evt: Event) => void) {
return from(checks).pipe(
concatMap((check: CanActivate) => {
return from([
fireChildActivationStart(check.route.parent, forwardEvent),
fireActivationStart(check.route, forwardEvent),
runCanActivateChild(futureSnapshot, check.path, moduleInjector),
runCanActivate(futureSnapshot, check.route, moduleInjector)
])
.pipe(concatAll(), first(result => {
return result !== true;
}, true as boolean | UrlTree));
return concat(
fireChildActivationStart(check.route.parent, forwardEvent),
fireActivationStart(check.route, forwardEvent),
runCanActivateChild(futureSnapshot, check.path, moduleInjector),
runCanActivate(futureSnapshot, check.route, moduleInjector));
}),
first(result => {
return result !== true;
Expand Down
3 changes: 1 addition & 2 deletions packages/router/src/operators/prioritized_guard_value.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ declare type INTERIM_VALUES = typeof INITIAL_VALUE | boolean | UrlTree;
export function prioritizedGuardValue():
OperatorFunction<Observable<boolean|UrlTree>[], boolean|UrlTree> {
return switchMap(obs => {
return combineLatest(
...obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE as INTERIM_VALUES))))
return combineLatest(obs.map(o => o.pipe(take(1), startWith(INITIAL_VALUE as INTERIM_VALUES))))
.pipe(
scan(
(acc: INTERIM_VALUES, list: INTERIM_VALUES[]) => {
Expand Down
14 changes: 6 additions & 8 deletions packages/router/src/operators/recognize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import {Type} from '@angular/core';
import {MonoTypeOperatorFunction, Observable} from 'rxjs';
import {MonoTypeOperatorFunction} from 'rxjs';
import {map, mergeMap} from 'rxjs/operators';

import {Route} from '../config';
Expand All @@ -19,11 +19,9 @@ export function recognize(
rootComponentType: Type<any>|null, config: Route[], serializer: (url: UrlTree) => string,
paramsInheritanceStrategy: 'emptyOnly'|'always',
relativeLinkResolution: 'legacy'|'corrected'): MonoTypeOperatorFunction<NavigationTransition> {
return function(source: Observable<NavigationTransition>) {
return source.pipe(mergeMap(
t => recognizeFn(
rootComponentType, config, t.urlAfterRedirects, serializer(t.urlAfterRedirects),
paramsInheritanceStrategy, relativeLinkResolution)
.pipe(map(targetSnapshot => ({...t, targetSnapshot})))));
};
return mergeMap(
t => recognizeFn(
rootComponentType, config, t.urlAfterRedirects, serializer(t.urlAfterRedirects),
paramsInheritanceStrategy, relativeLinkResolution)
.pipe(map(targetSnapshot => ({...t, targetSnapshot}))));
}
34 changes: 16 additions & 18 deletions packages/router/src/operators/resolve_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,23 @@ import {getToken} from '../utils/preactivation';
export function resolveData(
paramsInheritanceStrategy: 'emptyOnly'|'always',
moduleInjector: Injector): MonoTypeOperatorFunction<NavigationTransition> {
return function(source: Observable<NavigationTransition>) {
return source.pipe(mergeMap(t => {
const {targetSnapshot, guards: {canActivateChecks}} = t;
return mergeMap(t => {
const {targetSnapshot, guards: {canActivateChecks}} = t;

if (!canActivateChecks.length) {
return of(t);
}
let canActivateChecksResolved = 0;
return from(canActivateChecks)
.pipe(
concatMap(
check => runResolve(
check.route, targetSnapshot!, paramsInheritanceStrategy, moduleInjector)),
tap(() => canActivateChecksResolved++),
takeLast(1),
mergeMap(_ => canActivateChecksResolved === canActivateChecks.length ? of(t) : EMPTY),
);
}));
};
if (!canActivateChecks.length) {
return of(t);
}
let canActivateChecksResolved = 0;
return from(canActivateChecks)
.pipe(
concatMap(
check => runResolve(
check.route, targetSnapshot!, paramsInheritanceStrategy, moduleInjector)),
tap(() => canActivateChecksResolved++),
takeLast(1),
mergeMap(_ => canActivateChecksResolved === canActivateChecks.length ? of(t) : EMPTY),
);
});
}

function runResolve(
Expand Down
18 changes: 8 additions & 10 deletions packages/router/src/operators/switch_tap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {from, MonoTypeOperatorFunction, ObservableInput} from 'rxjs';
import {from, MonoTypeOperatorFunction, ObservableInput, of} from 'rxjs';
import {map, switchMap} from 'rxjs/operators';

/**
Expand All @@ -17,13 +17,11 @@ import {map, switchMap} from 'rxjs/operators';
*/
export function switchTap<T>(next: (x: T) => void|ObservableInput<any>):
MonoTypeOperatorFunction<T> {
return function(source) {
return source.pipe(switchMap(v => {
const nextResult = next(v);
if (nextResult) {
return from(nextResult).pipe(map(() => v));
}
return from([v]);
}));
};
return switchMap(v => {
const nextResult = next(v);
if (nextResult) {
return from(nextResult).pipe(map(() => v));
}
return of(v);
});
}
17 changes: 6 additions & 11 deletions packages/router/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -573,12 +573,11 @@ export class Router {
if (transition !== this.transitions.getValue()) {
return EMPTY;
}
return [t];
}),

// This delay is required to match old behavior that forced navigation
// to always be async
switchMap(t => Promise.resolve(t)),
// This delay is required to match old behavior that forced
// navigation to always be async
return Promise.resolve(t);
}),

// ApplyRedirects
applyRedirects(
Expand Down Expand Up @@ -609,10 +608,8 @@ export class Router {
}
this.browserUrlTree = t.urlAfterRedirects;
}
}),

// Fire RoutesRecognized
tap(t => {
// Fire RoutesRecognized
const routesRecognized = new RoutesRecognized(
t.id, this.serializeUrl(t.extractedUrl),
this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot!);
Expand Down Expand Up @@ -692,9 +689,7 @@ export class Router {
error.url = t.guardsResult;
throw error;
}
}),

tap(t => {
const guardsEnd = new GuardsCheckEnd(
t.id, this.serializeUrl(t.extractedUrl),
this.serializeUrl(t.urlAfterRedirects), t.targetSnapshot!,
Expand Down Expand Up @@ -875,7 +870,7 @@ export class Router {
replaceUrl: this.urlUpdateStrategy === 'eager'
};

return this.scheduleNavigation(
this.scheduleNavigation(
mergedTree, 'imperative', null, extras,
{resolve: t.resolve, reject: t.reject, promise: t.promise});
}, 0);
Expand Down
3 changes: 1 addition & 2 deletions packages/router/src/utils/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@

import {ɵisObservable as isObservable, ɵisPromise as isPromise} from '@angular/core';
import {from, Observable, of} from 'rxjs';
import {concatAll, last as lastValue, map} from 'rxjs/operators';

import {Params, PRIMARY_OUTLET} from '../shared';
import {Params} from '../shared';

export function shallowEqualArrays(a: any[], b: any[]): boolean {
if (a.length !== b.length) return false;
Expand Down

0 comments on commit 9105005

Please sign in to comment.