Angular 9 return Observable 来自 Observable

Angular 9 return Observable from an Observable

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

我正在使用 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.

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

您应该像这样订阅组件。

this.test().subscribe();

我创建了一个 stackblitz 来玩。

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

就像函数只有 运行 当你调用它们时里面的代码一样,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();
  }
  
}

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

冷可观察对象——顾名思义——在订阅之前不会开始处理它的内部语句。因此,在这种情况下,当您订阅组件时,它会触发所有可观察到的最内层 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 运算符,但没有 return 语句。在那种情况下,它将 return 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();
  }
}

有更优雅的方法可以关闭打开的订阅。看这里: