【问题标题】:Emit Observable value and handle it in component发出 Observable 值并在组件中处理它
【发布时间】:2020-04-25 11:02:42
【问题描述】:

我有一个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$ 的值未显示在NavbarComponent.html 中。

你能告诉我我做错了什么吗?

【问题讨论】:

    标签: angular rxjs observable angular-observable


    【解决方案1】:

    这样做:

    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();
    }
    

    【讨论】:

    • 感谢您的回复!你能否展示一下‘getAppUser()’不会被改变的方式,因为这个方法的逻辑比我展示的要多。
    • 您需要更改getAppUser,您实现它的方式是您代码中的问题。您所能做的就是通过像getAppUser() { /* whatever */ return this.userSource.asObservable(); } 一样将其保留为一个函数
    • 非常感谢!有用!您说过这是您的代码中的问题。我会很高兴听到如何改进这种方法。您能告诉我如何改进这种方法吗?
    【解决方案2】:

    通过从方法getUser() 返回of(this.user),您所做的就是返回一个具有单个发射的可观察对象,该发射是调用时this.user 的值。

    如果您希望每次用户通过登录更新时都会更新流,那么最好的方法是使用主题。 Subject 是一个 Observable,它的发射可以从外部设置。

    您可能想要使用一个名为 BehaviorSubject 的特殊主题,它也会在订阅后立即发出最后一个值。这样,如果在订阅 observable 后已经调用了 login,则仍将返回当前值。它等效于带有 startWithshareReplay 运算符的常规 observable。

    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() 中发生了其他逻辑,因此您可以在方法中执行相同的调用。

    【讨论】:

    • 感谢您的回复!你能否展示一下‘getAppUser()’不会被改变的方式,因为这个方法的逻辑比我展示的要多。
    猜你喜欢
    • 2017-08-02
    • 2021-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-26
    • 1970-01-01
    • 2018-11-04
    相关资源
    最近更新 更多