[英]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) });
}
As shown above, methodOne
set the value of globleVariable
and methodTwo
uses it, therefore the former must finish running before the latter.如上所示, methodOne
设置了methodTwo
globleVariable
它,因此前者必须先于后者运行完毕。
I am wondering how to achieve that.我想知道如何实现这一目标。
Instead of subscribing in the methods, combine them into one stream and subscribe to that in ngInit() .不要订阅方法,而是将它们组合成一个 stream 并在ngInit()中订阅它。 You can use tap to perform the side effect of updating globaleVariable that you were previously performing in subscribe() .您可以使用tap来执行您之前在subscribe()中执行的更新globaleVariable的副作用。
In the example below the "methods" are converted into fields since there is no reason for them to be methods anymore (you can keep them as methods if you want).在下面的示例中,“方法”被转换为字段,因为它们不再是方法(如果需要,您可以将它们保留为方法)。 Then the concat operator is used to create a single stream, where methodOne$ will execute and then when it's complete, methodTwo$ will execute.然后使用concat运算符创建单个 stream,其中 methodOne $将执行,然后当它完成时, methodTwo$将执行。
Because concat executes in order, you are guaranteed that globaleVariable will be set by methodOne$ before methodTwo$ begins.因为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();
}
You can create a subject for which observable 2 will wait to subscribe like below:-您可以创建一个主题,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) });
}
The only way to guarantee a method call after a subscription yields is to use the subscription callbacks.在订阅产生后保证方法调用的唯一方法是使用订阅回调。
Subscriptions have two main callbacks a success and a failure.订阅有两个主要回调成功和失败。
So the way to implement a method call after the subscription yeilds is to chain it like this:所以在订阅 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) });
}
You might want to chain the calls with some other rxjs operators for a more standard usage.您可能希望将调用与其他一些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) });
});
}
Please remember to complete any subscriptions when the component is destroyed to avoid the common memory leak .请记住在组件销毁时完成任何订阅,以避免常见的memory 泄漏。
my take,我的看法,
so it's a bit confusing when you use same service that throws different results, so instead of someService
I used firstService
and secondService
here.所以当你使用相同的服务但会抛出不同的结果时会有点混乱,所以我在这里使用firstService
和secondService
而不是someService
。
this.firstService.pipe(
switchMap(globalVariable) =>
this.secondService.pipe(
map(fields => Object.assign({}, globalVariable, { someField: fields }))
)
)
).subscribe(result => {
this.globalVariable = result;
})
What I like about this approach is that you have the flexibility on how you want to use the final result as it is decoupled with any of the property in your class.我喜欢这种方法的一点是,您可以灵活地使用最终结果,因为它与 class 中的任何属性都解耦了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.