避免在Angular 2+中嵌套订阅?

时间:2020-09-01 10:30:50

标签: angular rxjs

我有2个端点:

  • 1个端点来记录当前用户。
  • 1个端点来获得该用户的授权。

实际上我使用:

this.user
  .subscribe((e) => {
     this.grants.get(e)
        .subscribe((x) => {
            console.log(x)
         })
  })

但这是Angular 2 + / RxJS的反模式。

我想了解如何遵循Angular / RxJS最佳实践。

谢谢

3 个答案:

答案 0 :(得分:6)

Co依赖观测值

当可观察变量(this.grants.get())依赖于另一个可观察变量(this.user)的通知时,可以使用任何RxJS高阶映射运算符switchMapmergeMapconcatMapexhaustMap。每个人都有自己的目的。您可以找到它们here之间的区别。

他们之间的简短差异

  • switchMap-如果外部可观察到的发射,则取消内部可观察到的
  • mergeMap-触发每个外部通知的内部观察(展平外部通知)
  • concatMap-本质上是mergeMap,随时具有单个并发请求(展平外部通知,但按顺序发出它们)
  • exhaustMap-如果内部观察不到,则忽略外部通知

使用switchMap运算符的插图

this.user.pipe(
  switchMap(e => this.grants.get(e))
).subscribe((x) => {
  console.log(x)
});

独立的可观察物

如果可观察对象彼此独立,则可以使用forkJoincombineLatestzip之类的RxJS函数来并行触发可观察对象。

他们之间的简短差异

  • forkJoin α-仅在所有可观测值完成时发射
  • combineLatest α,β-当任何个可观察物发出时发出(不包含任何可观察物的观察物将发出旧值)
  • zip α,β-当所有个可观察物发射时发射

使用forkJoin

的插图
forkJoin(this.obs1, this.obs2, ...).subscribe(
  res => console.log(res)
);

α-从每个可观察对象发出一系列通知(例如(this.obs1, this.obs2, ...)将发出['res from obs1', 'res from obs2', ...])。

β-所有可观察物应该至少发射一次,以便操作员发射

答案 1 :(得分:0)

在您的代码中,看起来它们彼此之间没有依赖性,因为this.user的结果未在this.grants.get中使用,但我暂时将其忽略。

您可以使用await关键字来防止嵌套。

例如,您可以执行以下操作:

const user  = await this.user.toPromise();
const grants = await this.grants.get().toPromise();

答案 2 :(得分:0)

谢谢你们。它与switchMap一起使用。

import { Component, VERSION, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { switchMap } from 'rxjs/operators';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
  name = 'Angular ' + VERSION.major ;

  constructor(private http: HttpClient) {
  }

  ngOnInit() {
    this.http.get("https://pokeapi.co/api/v2/pokemon?limit=100&offset=200")
      .pipe(
        switchMap((mp) => {
          console.log("Requisição 01", mp);
          return this.http.get("https://pokeapi.co/api/v2");
        }),
        switchMap((it) => {
          console.log("Requisição 02", it);
          return this.http.get("https://pokeapi.co/api/v2/pokemon/206/");
        })
      )
      .subscribe((d) => console.log("subscribe", d))
  }
}
相关问题