【问题标题】:Typescript - Is calling another method inside the .subscribe() good or bad practice?Typescript - 在 .subscribe() 中调用另一个方法是好是坏?
【发布时间】:2017-01-04 10:02:36
【问题描述】:

这行得通,但我有点紧张,因为我不确定这只是一种技巧还是一种好的做法。有人可以告诉我这是一种技巧还是好的做法?

我这样做是为了确保第一种方法在启动第二种方法之前完全运行。

如果这是一种不好的做法,我敢肯定,请提供一种更好的方法来实现它。

我有一个方法调用 HTTP GET 方法,然后在订阅中绑定它并调用另一个方法,该方法使用该数据调用另一个服务。

 private bind(): void {

        this.Service.get(this.Id)
        .catch(this.logger.log)
        .subscribe(
        (customers: PersonalInfo[]) => { 

        this.customers = customers;               
                this.bindContactInfo();           
        }
        );
    }

private bindContactInfo():void{       

        this.Service.getContactInfo(this.Id)
        .catch(this.logger.log)
        .subscribe(   

        (contactInfo: ContactInformation[]) => {

         // stuff in here
        }
        );
        }  

【问题讨论】:

  • 在某些情况下,其他方法可能会更好(例如使用mergeMap),但从subscribe() 回调中调用其他方法并没有错。
  • 我正在按照您的方式进行操作(几乎)。也许我对这些方法的结构有点不同。如果我有两个单独的 HTTP 调用,但一个需要来自第一个的信息,我会按照您的方式进行操作。如果方法不相互依赖,但是我有第三种方法我想在数据加载后调用,我通常会做一个forkJoin,然后再调用第三种方法。

标签: angular typescript rxjs


【解决方案1】:

一般而言,您可以这样做,我认为在服务中这样做是可以的,但是如果您的代码来自组件并且由于您要求“良好做法”,这里有一些选项:

选项 1

您应该尽量避免手动订阅,使用.do(...) 进行此类操作。还要尽量避免无法单独使用各个部分的“硬链接”,因此请尝试将流分成较小的流,这样更容易测试。考虑到这些要点,我会这样写你的部分:

private getPersonalInfo(): Observable<PersonalInfo[]> {
    return this.Service.get(this.Id)
        .catch(this.logger.log)
        .do((customers: PersonalInfo[]) => this.customers = customers);
}

private getContactInfo(): Observable<ContactInformation[]> {
    return this.Service.getContactInfo(this.Id)
        .catch(this.logger.log)
        .do((contactInfo: ContactInformation[]) => this.contactInfo = contactInfo);
}

private getData(): void {
    this.getPersonalInfo()
        .switchMap(() => this.getContactInfo())
        .subscribe();
}

选项 2

由于我假设您在组件中使用它,因此我会尽量避免使用 this.contactInfo = contactInfo 之类的东西,并尝试在模板中使用 | async(因为我只使用组件来显示信息而不是在那里做任何计算)

id$: ReplaySubject<string> = new ReplaySubject<string>(1); // this comes possibly from a service or from an @Input

personalInfo$: Observable<PersonalInfo[]> = this.id$
        .switchMap(id => this.Service.get(id))
        .catch(this.logger.log)
        .publishReplay(1)
        .refCount();

contactInfo$: Observable<ContactInformation[]> = this.id$  // or start it with this.personalInfo$.switchMapTo(this.id$) if you want to make sure that it is executed AFTER the personalInfo was fetched
        .switchMap(id => this.Service.get(id))
        .getContactInfo(this.Id)
        .catch(this.logger.log)
        .publishReplay(1)
        .refCount();

在你的模板中你会这样使用它:

<div *ngFor="let personalInfo of personalInfo$ | async">
    ...
</div>

选项 3

使用一些存储概念,例如 ngrx - 这可能会导致很多重构。

【讨论】:

    猜你喜欢
    • 2018-10-10
    • 1970-01-01
    • 2011-12-06
    • 1970-01-01
    • 2017-07-30
    • 2016-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多