[英]Avoiding nesting subscriptions in Angular 2+?
我有 2 个端点:
其实我用:
this.user
.subscribe((e) => {
this.grants.get(e)
.subscribe((x) => {
console.log(x)
})
})
但这是 Angular 2+/RxJS 的反模式。
我想知道如何按照 Angular/RxJS 最佳实践来做到这一点。
谢谢
避免嵌套订阅取决于可观察对象的性质以及它们如何相互依赖:
当一个可观察对象 ( this.grants.get()
) 依赖于来自另一个可观察对象 ( this.user
) 的通知时,您可以使用任何 RxJS 高阶映射运算符switchMap
、 mergeMap
、 concatMap
和exhaustMap
。 每个人都有自己的目的。 您可以在 这里找到它们之间的区别。
他们之间的简要区别
switchMap
- 如果外部 observable 发出,则取消内部 observablemergeMap
- 为每个外部通知触发内部可观察对象(展平外部通知)concatMap
- 本质上是随时合并单个并发请求的mergeMap
(扁平化外部通知但按顺序发出)exhaustMap
- 如果内部 observable 尚未完成,则忽略外部通知使用switchMap
运算符的插图
this.user.pipe(
switchMap(e => this.grants.get(e))
).subscribe((x) => {
console.log(x)
});
如果可观察对象彼此独立,您可以使用 RxJS 函数,如forkJoin
、 combineLatest
或zip
来并行触发可观察对象。
他们之间的简要区别
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.