如何解决rxjs Observable 与预先解析的数据混合
我需要做的是检查当前用户是否具有admin角色,或者是否具有external角色并且当前帐户没有设置标志。但是如何使用 rxjs 做到这一点让我很困惑。
这是一个精简的测试用例,用于显示我正在尝试执行的操作,但是因为运行时所有数据都不存在(帐户为空,或者权限尚未加载) ,它出错了。
我怎样才能做到这一点?
我使用的是 rxjs6。
export class ViewComponent implements OnInit {
private account: AdminUser;
private permissions: Permissions;
constructor(private _service: AdminUserService,private _permissions: PermissionsService,private _activatedRoute: ActivatedRoute) {
}
canEdit(): boolean {
let isAdmin = this.permissions.hasRole('Admin');
return isAdmin || (this._permissions.hasRole('External') && !this.account.isActiveDirectory);
}
ngOnInit() {
this._permissions
.getPermissions()
.subscribe(p => this.permissions = p);
this._activatedRoute.params.subscribe(
params => {
this._service.get(params.id)
.pipe(map(account => this.account = account))
.subscribe();
});
}
}
解决方法
您可以将数据保留为可观察对象,而无需订阅您的组件。 Rxjs 有许多操作符和静态函数来对它们进行整形、过滤和转换以满足您的需求。
而不是将 account
定义为 AdminUser
并将 permissions
定义为 Permissions
;让我们将它们定义为 Observable<AdminUser>
和 Observable<Permissions>
。
然后我们可以使用 combineLatest
创建一个发出 canEdit
值的单个 observable。
export class ViewComponent {
private id$ = this._activatedRoute.params.pipe(map(params => params.id));
private account$ = this.id$.pipe(switchMap(id => this._service.get(id)));
private permissions$ = this._permissions.getPermissions();
public canEdit$ = combineLatest([this.account$,this.permissions$]).pipe(
map(([account,permissions]) =>
permissions.hasRole("Admin") ||
(permissions.hasRole("External") && !account.isActiveDirectory)
)
);
constructor(
private _service: AdminUserService,private _permissions: PermissionsService,private _activatedRoute: ActivatedRoute
) { }
}
如果您不熟悉 switchMap
,它基本上会为您订阅一个“内部 observable”并发出结果。在本例中,使用 id
并调用 service.get(id)
。
您似乎还希望将模板中的帐户信息与 canEdit
值一起使用。我们可以发出一个包含我们视图需要的所有数据的对象(视图模型),而不是发出单个 boolean
:
export class ViewComponent {
private id$ = this._activatedRoute.params.pipe(map(params => params.id));
private account$ = this.id$.pipe(switchMap(id => this._service.get(id)));
private permissions$ = this._permissions.getPermissions();
public vm$ = combineLatest([this.account$,permissions]) => {
const canEdit = permissions.hasRole("Admin") || (permissions.hasRole("External") && !account.isActiveDirectory)
return { account,canEdit };
})
);
constructor(
private _service: AdminUserService,private _activatedRoute: ActivatedRoute
) { }
}
您现在可以在模板中使用单个 async
管道来处理订阅:
<ng-container *ngIf="vm$ | async as vm">
<h1>{{ vm.account.name }}</h1>
...
<button *ngIf="vm.canEdit">Edit</button>
</ng-container>
,
我只是猜测您的目标可能是什么。但是检查你的代码,我认为你在寻找这样的解决方案。
export class ViewComponent implements OnInit,OnDestroy {
// provide this information as boolean
canEdit = false;
private account: AdminUser;
private permissions: Permissions;
// allways collect at start and remove all subscriptions when leaving the component
private subscription: Subscription = new Subscription();
constructor(private _service: AdminUserService,private _activatedRoute: ActivatedRoute) { }
ngOnInit(): void {
this.subscription.add(
this._permissions
.getPermissions()
.subscribe(permissions => {
this.permissions = permissions;
this.checkPermissions();
})
);
this.subscription.add(
this._activatedRoute.params.subscribe(
params => {
this._service.get(params.id).subscribe(account =>
this.account = account);
this.checkPermissions();
})
);
}
ngOnDestroy(): void {
// unsubscribe all subscriptions
this.subscription.unsubscribe();
}
checkPermissions(): void {
if (this.permissions && this.account) {
this.canEdit = this.permissions.hasRole('Admin') ||
(this._permissions.hasRole('External') && !this.account.isActiveDirectory);
}
}
在你的 HTML 中,我猜你想(取消)激活一个按钮左右。那就这样做吧。
<button [disabled]="!canEdit">Edit something</button>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。