英文:
How to wait for data in subscribe
问题
在Angular中,我在使用这个服务时遇到了问题。当我想要从后端通过令牌获取用户的角色,并在hasRole()
方法中检查这个角色时,我得到了未定义的数据。这是因为数据角色尚不存在。当我第二次运行这个服务时,它就正常工作了。如何获取数据并告诉服务等待它们。
export class JwtService {
roles: string[] = [];
constructor(
private http: HttpClient,
private loginService: LoginService
) { }
hasRole(rolea: string): boolean {
if (this.roles.length === 0) {
this.saveRole();
}
return this.roles.includes(rolea);
}
saveRole() {
this.http.get<string[]>(`/api/getRole/${this.getToken()}`).subscribe(role => this.roles = role);
}
}
英文:
I have a problem with this service in angular. When I want to get users' roles by token from backend and in method hasrole() check this role - I get undefined data. Because data roles don't exist yet. When I run this service a second time it works great. How to get data and tell service to wait for them.
export class JwtService {
roles: string[] = [];
constructor(
private http: HttpClient,
private loginService: LoginService
) { }
hasRole(rolea: string): boolean {
if (this.roles.length === 0) {
this.saveRole();
}
return this.roles.includes(rolea);
}
saveRole() {
this.http.get<string[]>(`/api/getRole/${this.getToken()}`).subscribe(role => this.roles = role);
}
}
答案1
得分: 1
更新 将"switchMap"替换为"map"
记住:"您的服务返回Observables,您在组件中订阅。"
您可以重构您的服务如下:
<strike>
// 见到返回一个 observable
// 您使用了rxjs运算符"of"
hasRole(rolea: string): Observable<boolean> {
if (this.roles.length === 0) {
return this.saveRole().pipe(
// 使用 switchMap,返回不是返回角色的 observable
// 而是一个 observable "true|false"
switchMap((roles: string[]) => {
this.roles = roles; // <-- 存储角色
return of(this.roles.includes(roles));
})
);
} else {
return of(this.roles.includes(roles));
}
}
</strike>
// 见到返回一个 observable
// 您使用了rxjs运算符"of"
hasRole(rolea: string): Observable<boolean> {
if (this.roles.length === 0) {
return this.saveRole().pipe(
map((roles: string[]) => {
this.roles = roles; // <-- 存储角色
return this.roles.includes(roles);
})
);
} else {
return of(this.roles.includes(roles));
}
}
// 我想象您的函数getToken()也返回一个 Observable
saveRole(): Observable<string[]> {
return this.getToken().pipe(
switchMap((token: string) =>
this.http.get<string[]>(`/api/getRole/${this.getToken()}`)
)
);
}
所以您可以使用类似以下的方式
<div *ngIf="myService.hasRole('admin') | async">
I am admin
</div>
英文:
Update replace the "switchMap" by "map"
Remember: "Your services return Observables, you subscribe in components."
You can re-structure your service in the way
<strike>
//see that return an observable
//You use rxjs operator "of"
hasRole(rolea: string): Observable<boolean> {
if (this.roles.length === 0) {
return this.saveRole().pipe(
//use switchMap, to return not the observable that return the roles
//else an observable "true|false"
switchMap((roles:string[])=>{
this.roles=roles; //<--store the roles
return of(this.roles.includes(roles))
})
)
}
else
return of(this.roles.includes(roles))
}
</strike>
//see that return an observable
//You use rxjs operator "of"
hasRole(rolea: string): Observable<boolean> {
if (this.roles.length === 0) {
return this.saveRole().pipe(
map((roles:string[])=>{
this.roles=roles; //<--store the roles
return this.roles.includes(roles)
})
)
}
else
return of(this.roles.includes(roles))
}
//I imagine that your function getToken() also return an Observable
saveRole():Observable<string[]> {
return this.getToken().pipe(
switchMap((token:string)=>
this.http.get<string[]>(`/api/getRole/${this.getToken()}`));
}
So you can use some like
<div *ngIf="myService.hasRole('admin')|async">
I am admin
</div>
答案2
得分: 1
hasRole
应该返回一个类似这样的 Observable
:
hasRole(role: string): Observable<boolean> {
if (this.roles.length === 0) {
return this.saveRole().pipe(
map(roles => roles.includes(role))
);
} else {
return of(this.roles.includes(role));
}
}
然后在你的组件中订阅它:
JwtService.hasRole('someRole').subscribe(hasRole => this.hsRole = hasRole);
tap
和 map
都是rxjs操作符,tap
用于副作用,而 map
用于将值映射为其他值 - 在你的情况下,将其映射为布尔值。
of
是一个rxjs函数,用于实例化一个Observable
并提供你提供的值。在这种情况下,我们使用它在不需要http
请求的情况下返回一个Observable
,因为数据已经被获取。
英文:
The hasRole
should return an Observable
like this:
hasRole(role: string): Observable<boolean>{
if (this.roles.length === 0) {
return this.saveRole().pipe(
map(roles => roles.includes(rolea))
);
}else{
return of(this.roles.includes(rolea));
}
saveRole(): Observable<string[]> {
return this.http.get<string[]>
(`/api/getRole/${this.getToken()}`).pipe(
tap(roles => this.roles = roles)
);
}
And then subscribe to it in your component:
JwtService.hasRole('someRole').subscribe(hasRole => this.hsRole = hasRole)
tap
& map
are both rxjs operators, tap
is for side effects and map
just maps the value into something else - in your case into a boolean.
of
is a rxjs function that instantiate an Observable
on go with the value you supply. In this case, we used it to return an Observable
when no http
request is needded since the data is already fetched.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论