繁体   English   中英

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

[英]Avoiding nesting subscriptions in Angular 2+?

我有 2 个端点:

  • 1 个端点以获取当前用户登录。
  • 1 个端点以获得此用户的授权。

其实我用:

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

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

我想知道如何按照 Angular/RxJS 最佳实践来做到这一点。

谢谢

避免嵌套订阅取决于可观察对象的性质以及它们如何相互依赖:

相互依赖的可观察量

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

他们之间的简要区别

  • switchMap - 如果外部 observable 发出,则取消内部 observable
  • mergeMap - 为每个外部通知触发内部可观察对象(展平外部通知)
  • concatMap - 本质上是随时合并单个并发请求的mergeMap (扁平化外部通知但按顺序发出)
  • exhaustMap - 如果内部 observable 尚未完成,则忽略外部通知

使用switchMap运算符的插图

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

独立的可观察量

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

他们之间的简要区别

  • forkJoin α - 仅在所有可观察对象完成时发出
  • combineLatest α,β - 当任何observables 发射时发射(没有发射的 observables 将发射旧值)
  • zip α,β - 当所有observable 发出时发出

使用forkJoin插图

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

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

β - 所有 observables应该至少发出一次供操作员发出

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

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

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

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

谢谢你们。 它与 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))
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM