mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Revert "refactor(router): Simplify the prioritizeGuardValue logic" (#46759)
This reverts commit f32fface4763d789a8b7cc4f4489f98be4e1073a. PR Close #46759
This commit is contained in:
@@ -7,43 +7,48 @@
|
||||
*/
|
||||
|
||||
import {combineLatest, Observable, OperatorFunction} from 'rxjs';
|
||||
import {filter, map, startWith, switchMap, take} from 'rxjs/operators';
|
||||
import {filter, map, scan, startWith, switchMap, take} from 'rxjs/operators';
|
||||
|
||||
import {UrlTree} from '../url_tree';
|
||||
import {isUrlTree} from '../utils/type_guards';
|
||||
|
||||
const INITIAL_VALUE = Symbol();
|
||||
const INITIAL_VALUE = Symbol('INITIAL_VALUE');
|
||||
declare type INTERIM_VALUES = typeof INITIAL_VALUE | boolean | UrlTree;
|
||||
|
||||
/**
|
||||
* Takes an array of observables and returns the result of the first to emit something other than
|
||||
* `true`.
|
||||
*
|
||||
* If all Observables emit `true`, then this operator emits true.
|
||||
* Also note that only the first value of each observable is used.
|
||||
*/
|
||||
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))))
|
||||
.pipe(
|
||||
map((results: INTERIM_VALUES[]) => {
|
||||
for (const result of results) {
|
||||
if (result === true) {
|
||||
// If result is true, check the next one
|
||||
continue;
|
||||
} else if (result === INITIAL_VALUE) {
|
||||
// If guard has not finished, we need to stop processing.
|
||||
return INITIAL_VALUE;
|
||||
} else {
|
||||
// Result finished and was not true. Return the result.
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// Everything resolved to true. Return true.
|
||||
return true;
|
||||
}),
|
||||
filter((item): item is boolean|UrlTree => item !== INITIAL_VALUE),
|
||||
take(1),
|
||||
);
|
||||
.pipe(
|
||||
scan(
|
||||
(acc: INTERIM_VALUES, list: INTERIM_VALUES[]) => {
|
||||
let isPending = false;
|
||||
return list.reduce((innerAcc, val, i: number) => {
|
||||
if (innerAcc !== INITIAL_VALUE) return innerAcc;
|
||||
|
||||
// Toggle pending flag if any values haven't been set yet
|
||||
if (val === INITIAL_VALUE) isPending = true;
|
||||
|
||||
// Any other return values are only valid if we haven't yet hit a pending
|
||||
// call. This guarantees that in the case of a guard at the bottom of the
|
||||
// tree that returns a redirect, we will wait for the higher priority
|
||||
// guard at the top to finish before performing the redirect.
|
||||
if (!isPending) {
|
||||
// Early return when we hit a `false` value as that should always
|
||||
// cancel navigation
|
||||
if (val === false) return val;
|
||||
|
||||
if (i === list.length - 1 || isUrlTree(val)) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
return innerAcc;
|
||||
}, acc);
|
||||
},
|
||||
INITIAL_VALUE),
|
||||
filter(item => item !== INITIAL_VALUE),
|
||||
map(item => isUrlTree(item) ? item : item === true), //
|
||||
take(1)) as Observable<boolean|UrlTree>;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user