发出 Observable 值并在组件中处理它
Emit Observable value and handle it in component
我有一个 login()
方法和一个 AuthService
。我想要的是从 AuthService
中的 login()
方法发出值来处理 NavbarComponent
:
中的值
export class AuthService extends AbstractRestService<any> {
user: AppUser = {id: null};
login(userName: string, password: string) {
return this.http
.post('/auth/login')
.pipe(
map(res => {
// here I want to emit value of Observable `anUser$`
// to send value to NavbarComponent
this.getAppUser(); // I want to throw Observable value to handle its value
// in NavbarComponent.ts
return true;
})
, catchError(this.handleError)
);
}
public getAppUser(): Observable<AppUser> {
return of(this.user);
}
}
我的 NavbarComponent.html
看起来像这样:
<li *ngIf="appUser$ | async as anUser">
{{ anUser?.name }}
</li>
我的 NavbarComponent.ts
看起来像这样:
appUser$: Observable<AppUser>;
async ngOnInit() {
this.appUser$ = this.auth.getAppUser();
}
我想要的是从 AuthService
中的 login()
方法发出值来处理 NavbarComponent
中的值,但是 appUser$
中的值未显示在 [=18] 中=].
你能告诉我我做错了什么吗?
这样做:
export class AuthService extends AbstractRestService<any> {
user: AppUser = {id: null};
login(userName: string, password: string) {
return this.http
.post('/auth/login')
.pipe(
map(res => {
this.userSource.next(res); // just call next with the user here
return true;
})
, catchError(this.handleError)
);
}
private userSource = new BehaviorSubject<AppUser>({id: null})
public getAppUser = this.userSource.asObservbale();
}
通过从方法 getUser()
返回 of(this.user)
,您所做的只是返回一个具有单个发射的可观察对象,即调用时 this.user
的值.
如果您想要一个每次用户通过登录更新时都会更新的流,那么最好的方法是使用 Subject。 Subject 是一个 Observable,它的发射可以从外部设置。
您可能想使用一个名为 BehaviorSubject 的特殊主题,它也会在订阅后立即发出最后一个值。这样,如果在订阅可观察对象后已调用登录,则仍将返回当前值。它等效于带有 startWith 和 shareReplay 运算符的常规可观察对象。
export class AuthService extends AbstractRestService<any> {
private readonly userSubject = new BehaviorSubject<{ id: string }>();
login(userName: string, password: string) {
return this.http
.post('/auth/login')
.pipe(
tap(res => userSubject.next(res)),
catchError(this.handleError)
);
}
getAppUser() {
/** do other work **/
return this.userSubject.asObservable();
}
}
就个人而言,我只是通过使用 this.userSubject.asObservable()
将 userSubject
公开为只读字段来直接分配变量。由于您指出 getAppUser()
中有其他逻辑发生,您可以在方法中执行相同的调用。
我有一个 login()
方法和一个 AuthService
。我想要的是从 AuthService
中的 login()
方法发出值来处理 NavbarComponent
:
export class AuthService extends AbstractRestService<any> {
user: AppUser = {id: null};
login(userName: string, password: string) {
return this.http
.post('/auth/login')
.pipe(
map(res => {
// here I want to emit value of Observable `anUser$`
// to send value to NavbarComponent
this.getAppUser(); // I want to throw Observable value to handle its value
// in NavbarComponent.ts
return true;
})
, catchError(this.handleError)
);
}
public getAppUser(): Observable<AppUser> {
return of(this.user);
}
}
我的 NavbarComponent.html
看起来像这样:
<li *ngIf="appUser$ | async as anUser">
{{ anUser?.name }}
</li>
我的 NavbarComponent.ts
看起来像这样:
appUser$: Observable<AppUser>;
async ngOnInit() {
this.appUser$ = this.auth.getAppUser();
}
我想要的是从 AuthService
中的 login()
方法发出值来处理 NavbarComponent
中的值,但是 appUser$
中的值未显示在 [=18] 中=].
你能告诉我我做错了什么吗?
这样做:
export class AuthService extends AbstractRestService<any> {
user: AppUser = {id: null};
login(userName: string, password: string) {
return this.http
.post('/auth/login')
.pipe(
map(res => {
this.userSource.next(res); // just call next with the user here
return true;
})
, catchError(this.handleError)
);
}
private userSource = new BehaviorSubject<AppUser>({id: null})
public getAppUser = this.userSource.asObservbale();
}
通过从方法 getUser()
返回 of(this.user)
,您所做的只是返回一个具有单个发射的可观察对象,即调用时 this.user
的值.
如果您想要一个每次用户通过登录更新时都会更新的流,那么最好的方法是使用 Subject。 Subject 是一个 Observable,它的发射可以从外部设置。
您可能想使用一个名为 BehaviorSubject 的特殊主题,它也会在订阅后立即发出最后一个值。这样,如果在订阅可观察对象后已调用登录,则仍将返回当前值。它等效于带有 startWith 和 shareReplay 运算符的常规可观察对象。
export class AuthService extends AbstractRestService<any> {
private readonly userSubject = new BehaviorSubject<{ id: string }>();
login(userName: string, password: string) {
return this.http
.post('/auth/login')
.pipe(
tap(res => userSubject.next(res)),
catchError(this.handleError)
);
}
getAppUser() {
/** do other work **/
return this.userSubject.asObservable();
}
}
就个人而言,我只是通过使用 this.userSubject.asObservable()
将 userSubject
公开为只读字段来直接分配变量。由于您指出 getAppUser()
中有其他逻辑发生,您可以在方法中执行相同的调用。