【问题标题】:Angular 9 return Observable from an ObservableAngular 9 从 Observable 返回 Observable
【发布时间】:2021-09-24 12:45:12
【问题描述】:

我正在寻找一种从另一个 Observable 返回 Observable 的方法。我发现您可以使用 pipema​​p 运算符来做到这一点,但它似乎对我不起作用。我做错了什么?

我正在使用 Angular 9.1.12rxjs ~6.5.4

示例: 服务1

import { Observable, of } from 'rxjs';

export class Service1 {

  test(): Observable<string> {
      console.log(1);
      return of('hey');
  }
}

服务2

import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export class Service2 {

  constructor(private service1: Service1) {}

  test(): Observable<string> {
    return this.service1.test().pipe(
      map((value: string) => {
        console.log(2);
        return value;
      })
    );
  }
}

组件

import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export class Component implements OnInit {

  constructor(private service2: Service2) {}

  test(): Observable<void> {
    return this.service2.test().pipe(
      map((value: string) => {
        console.log(3);
      }));
    }
  }
}

控制台只会输出1

【问题讨论】:

  • 您在哪里以及如何订阅?
  • 哦,天哪,我在组件调用中添加了 .subscribe(),它现在可以工作了,太好了。您可以发布答案,我会接受。谢谢。

标签: angular typescript rxjs pipe observable


【解决方案1】:

这是合理的,因为您从未订阅 observables,因此它们从未实际发出或运行。

你应该像这样订阅组件。

this.test().subscribe();

我创建了一个stackblitz 来玩。

PS:请注意,您还必须在需要时取消订阅。如果您对这些概念不熟悉,建议您阅读that 文章。

【讨论】:

    【解决方案2】:

    正如函数仅在您调用它们时运行其内部代码一样,Observables 仅在您订阅它们时运行它们的代码。

    您看到1 输出是因为您调用了this.service1.test()

    您看不到23,因为您从未订阅过Observables

    export class Component implements OnInit {
    
      constructor(private service2: Service2) {}
    
      test(): void {
        this.service2.test().pipe(
          map(_ => console.log(3))
        ).subscribe();
      }
      
    }
    

    【讨论】:

      【解决方案3】:

      有两种类型的 observables:热的和冷的。我不会讨论热门的可观察对象,因为它与这个问题没有任何关系。您可以找到更多信息here

      Cold observables - 顾名思义 - 在订阅之前不要开始处理它的内部语句。所以在这种情况下,当你订阅组件时,它会触发所有的 observable,直到最里面的of('hey')

      export class Component implements OnInit {
        constructor(private service2: Service2) {}
      
        ngOnInit() {
          this.test().subscribe();
        }
      
        test(): Observable<void> {
          return this.service2.test().pipe(
            tap((value: string) => console.log(value))
          );
        }
      }
      

      这里还有一点需要注意,您在组件中使用了map 运算符而没有返回语句。在这种情况下,它将返回undefinedmap 一般用于转换传入的语句。 tap 运算符更适合这里。它用于执行副作用。

      退订

      此外,除非发出错误或明确完成,否则打开的订阅不会关闭。因此,在使用后关闭打开的订阅总是一个好主意。

      例如。在 Angular 中,通常的做法是在 ngOnDestroy 钩子中关闭它,以便在关闭组件时关闭它。

      export class Component implements OnInit, OnDestroy {
        sub: Subscription;
      
        constructor(private service2: Service2) {}
      
        ngOnInit() {
          this.sub = this.test().subscribe();
        }
      
        test(): Observable<void> {
          return this.service2.test().pipe(
            tap((value: string) => console.log(value))
          );
        }
      
        ngOnDestroy() {
          if (!!this.sub)
            this.sub.unsubscribe();
        }
      }
      

      有更优雅的方式来关闭打开的订阅。见这里:https://stackoverflow.com/a/60223749/6513921

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-12
        • 1970-01-01
        • 1970-01-01
        • 2018-07-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多