繁体   English   中英

如何确保一个订阅在另一个订阅之前完成?

[英]How do I make sure one Subcription finishes before another?

globleVariable: any;

ngOnInit() {
    // This doesn't work. methodTwo throws error saying "cannot read someField from null. "
    this.methodOne();
    this.methodTwo();
}

methodOne() {
    this.firstService.subscribe((res) => { this.globleVariable = res });
}

methodTwo() {
    this.secondService.subscribe((res) => { console.log(this.globleVariable.someField) });
}

如上所示, methodOne设置了methodTwo globleVariable它,因此前者必须先于后者运行完毕。

我想知道如何实现这一目标。

不要订阅方法,而是将它们组合成一个 stream 并在ngInit()中订阅它。 您可以使用tap来执行您之前在subscribe()中执行的更新globaleVariable的副作用。

在下面的示例中,“方法”被转换为字段,因为它们不再是方法(如果需要,您可以将它们保留为方法)。 然后使用concat运算符创建单个 stream,其中 methodOne $将执行,然后当它完成时, methodTwo$将执行。

因为concat按顺序执行,所以可以保证globaleVariable将在methodTwo$开始之前由 methodOne $设置。

globleVariable: any;
methodOne$ = this.someService.pipe(tap((res) => this.globleVariable = res));
methodTwo$ = this.someService.pipe(tap((res) => console.log(this.globleVariable.someField));

ngOnInit() {
  concat(this.methodOne$, this.methodTwo$).subscribe();
}

您可以创建一个主题,observable 2 将等待订阅,如下所示:-

globalVariable: any;

subject: Subject = new Subject();

methodOne() {
    this.someService.subscribe((res) => { this.globleVariable = res; this.subject.next(); });
}

methodTwo() {
    this.subject.pipe(take(1), mergeMap(() => this.someService)).subscribe((res) => { 
          console.log(this.globleVariable.someField) });
}

在订阅产生后保证方法调用的唯一方法是使用订阅回调。

订阅有两个主要回调成功和失败。

所以在订阅 yields 之后实现方法调用的方法是像这样链接它:

globleVariable: any;

ngOnInit() {
    this.methodOne();
}

methodOne() {
    this.someService.subscribe((res) => {
       this.globleVariable = res
       this.methodTwo(); // <-- here, in the callback
    });
}

methodTwo() {
    this.someService.subscribe((res) => { console.log(this.globleVariable.someField) });
}

您可能希望将调用与其他一些rxjs 操作员链接起来以获得更标准的用法。

ngOnInit() {
  this.someService.method1.pipe(
    take(1),
    tap(res1 => this.globleVariable = res1)
    switchmap(res1 => this.someService.method2), // <-- when first service call yelds success
    catchError(err => { // <-- failure callback
                console.log(err);
                return throwError(err)
            }),
  ).subscribe(res2 => { //  <-- when second service call yelds success
    console.log(this.globleVariable.someField) });
  });
}

请记住在组件销毁时完成任何订阅,以避免常见的memory 泄漏

我的看法,

所以当你使用相同的服务但会抛出不同的结果时会有点混乱,所以我在这里使用firstServicesecondService而不是someService

this.firstService.pipe(
  switchMap(globalVariable) => 
    this.secondService.pipe(
      map(fields => Object.assign({}, globalVariable, { someField: fields }))
    )
  )
).subscribe(result => {
  this.globalVariable = result;
})

我喜欢这种方法的一点是,您可以灵活地使用最终结果,因为它与 class 中的任何属性都解耦了。

暂无
暂无

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

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