可观察<Observable<T>> 到可观察<T>
Observable<Observable<T>> to Observable<T>
这里是 RxJS 新手。使用 Angular 6. 试图找出如何从 Observable<Observable<T>>
得到 Observable<T>
。不确定这是否有效并且很难从概念上理解它,但这似乎是一个简单的问题。
我研究过 switchMap、flatMap、forJoin,但我认为它们不符合我的需要。
我想做的是 Angular 路由保护,它将阻止用户访问路由,除非他们具有必要的权限。 2 依赖项是一个用户配置文件,用于获取他们的信息,然后用于获取他们的权限。这种混合导致 Observable of Observable 问题。这是我得到的:
export class AuthPermissionsRouteGuard implements CanActivate {
constructor(
private router: Router,
private authService: AuthPermissionsService,
private openIdService: AuthOpenIdService) {}
/**Navigates to route if user has necessary permission, navigates to '/forbidden' otherwise */
canActivate(routeSnapshot: ActivatedRouteSnapshot): Observable<boolean> {
return this.canNavigateToRoute(routeSnapshot.data['permissionId'] as number);
}
/**Waits on a valid user profile, once we get one - checks permissions */
private canNavigateToRoute(permissionId: number): Observable<boolean> {
const observableOfObservable = this.openIdService.$userProfile
.pipe(
filter(userProfile => userProfile ? true : false),
map(_ => this.hasPermissionObservable(permissionId)));
// Type Observable<Observable<T>> is not assignable to Observable<T> :(
return observableOfObservable;
}
/**Checks if user has permission to access desired route and returns the result. Navigates to '/forbidden' if no permissions */
private hasPermissionObservable(permissionId: number): Observable<boolean> {
return this.permissionsService.hasPermission(permissionId).pipe(
map(hasPermission => {
if (!hasPermission) {
this.router.navigate(['/forbidden']);
}
return hasPermission;
}
));
}
}
非常感谢!!
就目前而言,您从 hasPermissionObservable
函数返回一个 Observable,它将被包装在 map operator
.
的一个 observable 中
您需要查看 mergeMap/flatMap operator
or contactMap operator
。
MergeMap: This operator is best used when you wish to flatten an inner observable but want to manually control the number of inner subscriptions. Example from the Learn RXJS link:
// RxJS v6+
import { of } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
// emit 'Hello'
const source = of('Hello');
// map to inner observable and flatten
const example = source.pipe(mergeMap(val => of(`${val} World!`)));
// output: 'Hello World!'
const subscribe = example.subscribe(val => console.log(val));
ContactMap: Map values to inner observable, subscribe and emit in order. Example from the Learn RXJS link:
// RxJS v6+
import { of } from 'rxjs';
import { concatMap } from 'rxjs/operators';
// emit 'Hello' and 'Goodbye'
const source = of('Hello', 'Goodbye');
// example with promise
const examplePromise = val => new Promise(resolve => resolve(`${val} World!`));
// map value from source into inner observable, when complete emit result and move to next
const example = source.pipe(concatMap(val => examplePromise(val)));
// output: 'Example w/ Promise: 'Hello World', Example w/ Promise: 'Goodbye World'
const subscribe = example.subscribe(val =>
console.log('Example w/ Promise:', val)
);
所以对于你的例子:
/**Waits on a valid user profile, once we get one - checks permissions */
private canNavigateToRoute(permissionId: number): Observable<boolean> {
const observableOfObservable = this.openIdService.$userProfile
.pipe(
filter(userProfile => userProfile ? true : false),
concatMap(_ => this.hasPermissionObservable(permissionId))); // <- try changes here
// Type Observable<Observable<T>> is not assignable to Observable<T> :(
return observableOfObservable;
}
这里是 RxJS 新手。使用 Angular 6. 试图找出如何从 Observable<Observable<T>>
得到 Observable<T>
。不确定这是否有效并且很难从概念上理解它,但这似乎是一个简单的问题。
我研究过 switchMap、flatMap、forJoin,但我认为它们不符合我的需要。
我想做的是 Angular 路由保护,它将阻止用户访问路由,除非他们具有必要的权限。 2 依赖项是一个用户配置文件,用于获取他们的信息,然后用于获取他们的权限。这种混合导致 Observable of Observable 问题。这是我得到的:
export class AuthPermissionsRouteGuard implements CanActivate {
constructor(
private router: Router,
private authService: AuthPermissionsService,
private openIdService: AuthOpenIdService) {}
/**Navigates to route if user has necessary permission, navigates to '/forbidden' otherwise */
canActivate(routeSnapshot: ActivatedRouteSnapshot): Observable<boolean> {
return this.canNavigateToRoute(routeSnapshot.data['permissionId'] as number);
}
/**Waits on a valid user profile, once we get one - checks permissions */
private canNavigateToRoute(permissionId: number): Observable<boolean> {
const observableOfObservable = this.openIdService.$userProfile
.pipe(
filter(userProfile => userProfile ? true : false),
map(_ => this.hasPermissionObservable(permissionId)));
// Type Observable<Observable<T>> is not assignable to Observable<T> :(
return observableOfObservable;
}
/**Checks if user has permission to access desired route and returns the result. Navigates to '/forbidden' if no permissions */
private hasPermissionObservable(permissionId: number): Observable<boolean> {
return this.permissionsService.hasPermission(permissionId).pipe(
map(hasPermission => {
if (!hasPermission) {
this.router.navigate(['/forbidden']);
}
return hasPermission;
}
));
}
}
非常感谢!!
就目前而言,您从 hasPermissionObservable
函数返回一个 Observable,它将被包装在 map operator
.
您需要查看 mergeMap/flatMap operator
or contactMap operator
。
MergeMap: This operator is best used when you wish to flatten an inner observable but want to manually control the number of inner subscriptions. Example from the Learn RXJS link:
// RxJS v6+
import { of } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
// emit 'Hello'
const source = of('Hello');
// map to inner observable and flatten
const example = source.pipe(mergeMap(val => of(`${val} World!`)));
// output: 'Hello World!'
const subscribe = example.subscribe(val => console.log(val));
ContactMap: Map values to inner observable, subscribe and emit in order. Example from the Learn RXJS link:
// RxJS v6+
import { of } from 'rxjs';
import { concatMap } from 'rxjs/operators';
// emit 'Hello' and 'Goodbye'
const source = of('Hello', 'Goodbye');
// example with promise
const examplePromise = val => new Promise(resolve => resolve(`${val} World!`));
// map value from source into inner observable, when complete emit result and move to next
const example = source.pipe(concatMap(val => examplePromise(val)));
// output: 'Example w/ Promise: 'Hello World', Example w/ Promise: 'Goodbye World'
const subscribe = example.subscribe(val =>
console.log('Example w/ Promise:', val)
);
所以对于你的例子:
/**Waits on a valid user profile, once we get one - checks permissions */
private canNavigateToRoute(permissionId: number): Observable<boolean> {
const observableOfObservable = this.openIdService.$userProfile
.pipe(
filter(userProfile => userProfile ? true : false),
concatMap(_ => this.hasPermissionObservable(permissionId))); // <- try changes here
// Type Observable<Observable<T>> is not assignable to Observable<T> :(
return observableOfObservable;
}