【问题标题】:Angular 12, RxJS: safe to use takeWhile without onDestroy?Angular 12,RxJS:在没有 onDestroy 的情况下安全使用 takeWhile?
【发布时间】:2021-09-26 09:57:23
【问题描述】:

我对@9​​87654322@ 有一个普遍的困惑。

我想要达到的目标:

  • 等待fireAuthUser$ Observable 有值
  • 一旦发生,做一些事情
  • 如果fireAuthUser$ Observable 没有收到值,则在组件离开后取消
export class AuthService implements OnDestroy {
    fireAuthUser: BehaviorSubject<firebase.User | undefined> = new BehaviorSubject<firebase.User | undefined>(undefined);
    public readonly fireAuthUser$: Observable<firebase.User | undefined> = this.fireAuthUser.asObservable();
    private subscription?: Subscription;

    constructor(public fire: AngularFireAuth) {
        this.subscription = this.fire.authState.subscribe((fireAuthUser) => {
            if (fireAuthUser) {
                this.fireAuthUser.next(fireAuthUser);
                // ...
            }
        });
    }

    ngOnDestroy(): void {
        this.subscription?.unsubscribe();
    }

    doSomeStuff(): void {
       //do some stuff
    }

}
export class Foo implements OnInit {

    constructor(public auth: AuthService) { }

    ngOnInit(): void {
         this.auth.fireAuthUser$.pipe(takeWhile((fireAuthUser) => fireAuthUser === undefined)).subscribe({
          complete: () => this.auth.doSomeStuff()
        });
    }

}

上面的代码有效。但是,根据Angular/RxJS When should I unsubscribe from `Subscription` 使用takeWhile,在组件的ngDestroy 上不会取消可观察执行。所以根据我的理解,我需要在我的ngOnDestroy 中手动设置一个.next 值,否则我的takeWhile 永远不会取消?用例是,即,如果用户无法登录(不存在fireAuthUser

但是,我想我不能简单地放一个ngOnDestroy(): void { this.auth.fireAuthUser.next(undefined); },因为这总是会删除我的fireAuthUser,如果用户确实有一个fireAuthUser 对象,这是一个问题吗?那么在这种情况下我应该怎么做呢?还是我误解了这句话,我的代码可以安全使用?

【问题讨论】:

  • 为什么不能直接实现OnDestroy保存订阅并取消订阅?

标签: angular typescript rxjs


【解决方案1】:

使用takeUntil 运算符。它会监听this.auth.fireAuthUser$,直到当前组件被销毁

import { Subject, takeUntil } from 'rxjs';

export class Foo implements OnInit{
  private destroy$ = new Subject();
  constructor() {}

  ngOnInit(): void {
    this.auth.fireAuthUser$
      .pipe(takeUntil(this.destroy$))
      .subscribe({
        next: (data) => console.log(data),
        complete: () => this.uponComplete(),
      });
  }

  uponComplete() {
    console.log('Finally completed');
  }

  ngOnDestroy() {
    this.destroy$.next(true);
    this.destroy$.complete();
  }
}

查看演示here(点击Go to Auth计时器将启动,点击Home它将取消订阅)

【讨论】:

    【解决方案2】:

    使用takeUntil 运算符。 我喜欢创建一个 BaseComponent 来扩展具有 observable 的类。

    @Component({
        template: ''
    })
    export abstract class BaseComponent implements OnDestroy {
        protected unsubscribe: Subject<void> = new Subject();
    
        ngOnDestroy(): void {
            this.destroy();
        }
    
        private destroy(): void {
            this.unsubscribe.next();
            this.unsubscribe.complete();
        }
    }
    

    在这个类之后,你可以扩展你想要的所有类,并在组件被销毁时使用takeUntil方法销毁observable。

    export class LeadEditComponent extends BaseComponent implements OnInit {
        ngOnInit(): void {
             this.subscription = this.fire.authState
                .pipe(
                     takeUntil(this.unsubscribe)
                 )
                .subscribe((fireAuthUser) => {
                    if (fireAuthUser) {
                        this.fireAuthUser.next(fireAuthUser);
                        // ...
                    }
             });
        }
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用ngOnDestroy 取消订阅吗?

      export class Foo implements OnInit {
      
          private sub: Subscription;
          constructor(public auth: AuthService) { }
      
          ngOnInit(): void {
               this.sub = this.auth.fireAuthUser$.pipe(takeWhile((fireAuthUser) => fireAuthUser === undefined)).subscribe({
                complete: () => this.auth.doSomeStuff()
              });
          }
      
          ngOnDestroy() {
            this.sub.unsubscribe()
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-04-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-29
        • 1970-01-01
        • 2016-12-20
        相关资源
        最近更新 更多