Skip to content

Commit 2e78b76

Browse files
awerlangvikerman
authored andcommitted
fix(router): resolve guard observables on the first emit (#10412)
1 parent b2cf379 commit 2e78b76

File tree

2 files changed

+21
-16
lines changed

2 files changed

+21
-16
lines changed

modules/@angular/router/src/router.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ import {fromPromise} from 'rxjs/observable/fromPromise';
1717
import {of } from 'rxjs/observable/of';
1818
import {concatMap} from 'rxjs/operator/concatMap';
1919
import {every} from 'rxjs/operator/every';
20+
import {first} from 'rxjs/operator/first';
2021
import {map} from 'rxjs/operator/map';
21-
import {mergeAll} from 'rxjs/operator/mergeAll';
2222
import {mergeMap} from 'rxjs/operator/mergeMap';
2323
import {reduce} from 'rxjs/operator/reduce';
2424

@@ -783,7 +783,7 @@ export class PreActivation {
783783
checkGuards(): Observable<boolean> {
784784
if (this.checks.length === 0) return of (true);
785785
const checks$ = from(this.checks);
786-
const runningChecks$ = map.call(checks$, (s: any) => {
786+
const runningChecks$ = mergeMap.call(checks$, (s: any) => {
787787
if (s instanceof CanActivate) {
788788
return andObservables(
789789
from([this.runCanActivateChild(s.path), this.runCanActivate(s.route)]));
@@ -795,8 +795,7 @@ export class PreActivation {
795795
throw new Error('Cannot be reached');
796796
}
797797
});
798-
const mergedChecks$ = mergeAll.call(runningChecks$);
799-
return every.call(mergedChecks$, (result: any) => result === true);
798+
return every.call(runningChecks$, (result: any) => result === true);
800799
}
801800

802801
resolveData(): Observable<any> {
@@ -898,11 +897,13 @@ export class PreActivation {
898897
if (!canActivate || canActivate.length === 0) return of (true);
899898
const obs = map.call(from(canActivate), (c: any) => {
900899
const guard = this.getToken(c, future);
900+
let observable: Observable<boolean>;
901901
if (guard.canActivate) {
902-
return wrapIntoObservable(guard.canActivate(future, this.future));
902+
observable = wrapIntoObservable(guard.canActivate(future, this.future));
903903
} else {
904-
return wrapIntoObservable(guard(future, this.future));
904+
observable = wrapIntoObservable(guard(future, this.future));
905905
}
906+
return first.call(observable);
906907
});
907908
return andObservables(obs);
908909
}
@@ -918,11 +919,13 @@ export class PreActivation {
918919
return andObservables(map.call(from(canActivateChildGuards), (d: any) => {
919920
const obs = map.call(from(d.guards), (c: any) => {
920921
const guard = this.getToken(c, c.node);
922+
let observable: Observable<boolean>;
921923
if (guard.canActivateChild) {
922-
return wrapIntoObservable(guard.canActivateChild(future, this.future));
924+
observable = wrapIntoObservable(guard.canActivateChild(future, this.future));
923925
} else {
924-
return wrapIntoObservable(guard(future, this.future));
926+
observable = wrapIntoObservable(guard(future, this.future));
925927
}
928+
return first.call(observable);
926929
});
927930
return andObservables(obs);
928931
}));
@@ -938,16 +941,17 @@ export class PreActivation {
938941
private runCanDeactivate(component: Object, curr: ActivatedRouteSnapshot): Observable<boolean> {
939942
const canDeactivate = curr && curr._routeConfig ? curr._routeConfig.canDeactivate : null;
940943
if (!canDeactivate || canDeactivate.length === 0) return of (true);
941-
const canDeactivate$ = map.call(from(canDeactivate), (c: any) => {
944+
const canDeactivate$ = mergeMap.call(from(canDeactivate), (c: any) => {
942945
const guard = this.getToken(c, curr);
946+
let observable: Observable<boolean>;
943947
if (guard.canDeactivate) {
944-
return wrapIntoObservable(guard.canDeactivate(component, curr, this.curr));
948+
observable = wrapIntoObservable(guard.canDeactivate(component, curr, this.curr));
945949
} else {
946-
return wrapIntoObservable(guard(component, curr, this.curr));
950+
observable = wrapIntoObservable(guard(component, curr, this.curr));
947951
}
952+
return first.call(observable);
948953
});
949-
const merged$ = mergeAll.call(canDeactivate$);
950-
return every.call(merged$, (result: any) => result === true);
954+
return every.call(canDeactivate$, (result: any) => result === true);
951955
}
952956

953957
private runResolve(future: ActivatedRouteSnapshot): Observable<any> {

modules/@angular/router/test/integration.spec.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {Component, NgModule, NgModuleFactoryLoader} from '@angular/core';
1111
import {ComponentFixture, TestBed, async, fakeAsync, inject, tick} from '@angular/core/testing';
1212
import {expect} from '@angular/platform-browser/testing/matchers';
1313
import {Observable} from 'rxjs/Observable';
14-
import {of } from 'rxjs/observable/of';
1514
import {map} from 'rxjs/operator/map';
1615

1716
import {ActivatedRoute, ActivatedRouteSnapshot, CanActivate, CanDeactivate, Event, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, PRIMARY_OUTLET, Params, PreloadAllModules, PreloadingStrategy, Resolve, Router, RouterModule, RouterStateSnapshot, RoutesRecognized, UrlHandlingStrategy, UrlSegmentGroup, UrlTree} from '../index';
@@ -1163,7 +1162,9 @@ describe('Integration', () => {
11631162
TestBed.configureTestingModule({
11641163
providers: [{
11651164
provide: 'CanActivate',
1166-
useValue: (a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => of (false),
1165+
useValue: (a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => {
1166+
return Observable.create((observer: any) => { observer.next(false); });
1167+
}
11671168
}]
11681169
});
11691170
});
@@ -1438,7 +1439,7 @@ describe('Integration', () => {
14381439
providers: [{
14391440
provide: 'CanDeactivate',
14401441
useValue: (c: TeamCmp, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => {
1441-
return of (false);
1442+
return Observable.create((observer: any) => { observer.next(false); });
14421443
}
14431444
}]
14441445
});

0 commit comments

Comments
 (0)