[英]Angular Typescript return type for nested subscriptions
I have a function which calls multiple service methods. 我有一个调用多种服务方法的函数。 This function resides in a service object, which i need to call from the app.component.ts, from there i need to wait until this functions is completed to execute more code.
该函数驻留在服务对象中,我需要从app.component.ts调用该服务对象,从那里我需要等到该函数完成以执行更多代码。 My question is how can i change the return type of this so that i can subscribe to it from app.component.ts My code is as below.
我的问题是我该如何更改其返回类型,以便可以从app.component.ts订阅它。我的代码如下。
public registerAndGetToken() {
this.initializeRegistration().subscribe((match)=> {
// if initialization is success then invoke callback function
// initializationCallback() will return a boolean (synchronous function)
const callbackResult = this.initializationCallback(match);
if(callbackResult) {
this.renewToken().subscribe((tokenResult)=> {
//renewTokenCallback is a synchronous function
this.renewTokenCallback();
//what to return from here??
},
(tokenError) => {
//what to return from here??
});
}
else {
// what to return from here??
}
},
(error) => {
// what to return from here??
});
I tried to add a "return" on this.initializeRegistration()
line and then return Observable.of(true);
我试图在
this.initializeRegistration()
行上添加“ return”,然后return Observable.of(true);
this.initializeRegistration()
and change the method signature to public registerAndGetToken(): Observable<boolean>
. 并将方法签名更改为public
registerAndGetToken(): Observable<boolean>
。 But it doesn't like it. 但它不喜欢它。 Says
说
Type 'Subscription' is not assignable to type 'Observable'.
无法将“订阅”类型分配给“可观察”类型。
Property '_isScalar' is missing in type 'Subscription'.“预订”类型中缺少属性“ _isScalar”。 [2322]
[2322]
You've got way too many subscribes. 您订阅的方式太多了。 :)
:)
I heard some good advice once about Observables - "be suspicious of a subscribe within a subscribe". 我曾经听说过一些有关Observables的好建议-“怀疑订阅内的订阅”。 That's pretty good advice because it probably means I'm approaching the problem incorrectly if I am doing that.
这是一个很好的建议,因为这可能意味着如果我这样做的话,我将错误地解决该问题。 As a general rule of thumb I also tend not to subscribe within a service, but leave that for the component (or better yet just for the template of the component).
作为一般经验法则,我也倾向于不订阅服务,而是将其留给组件(或者更好的是留给组件的模板)。 Otherwise there is too much opportunity for memory leaks, trying to make sure I unsubscribe them all.
否则,内存泄漏的机会就太多了,试图确保我全部取消订阅。
In your case I am glad you specify rxjs 5.5 because that is when the .pipe operator was introduced and that will make your code significantly easier to write I think. 对于您的情况,我很高兴指定rxjs 5.5,因为那是在引入.pipe运算符时开始的,我认为这将使您的代码更容易编写。 There is much I do not know about your code, so I offer the following not as a cut-and-paste solution, but rather as an example of how to refactor this to take out all the subscribes from your service, and ultimately return an observable which can be subscribed to in your component, as you stated in your question.
我对您的代码不了解很多,因此,我提供的内容并不是剪切和粘贴的解决方案,而是作为示例,说明如何对其进行重构以从服务中删除所有订阅,并最终返回一个可观察到的,可以在您的组件中进行订阅,如您在问题中所述。
Here is some code you can think about: 这是您可以考虑的一些代码:
public registerAndGetToken() {
return this.initializeRegistration().pipe( // <-- return an Observable
catchError((error) => {
// handle case when initializeRegistration gives back an error,
// for example:
return throwError(`initializeRegistration() threw error: ${error.message}`);
// This assumes the error will be bubbled up to the component
}),
mergeMap((match) => {
const callbackResult = this.initializationCallback(match);
if(callbackResult) {
return this.renewToken().pipe(
tap((tokenResult)=> {
// Your example never uses tokenResult for anything ...
// so I'll assume you actually want tokenResult to bubble
// up all the way your component as the result ...
this.renewTokenCallback(); // This makes no sense to me ...
// why have a callback here?
}),
catchError((tokenError) => {
// add code to handle renewToken() returning an error
return tokenError;
})
)
}
else {
// return something that can be handled inside the component
// when callbackResult is false.
// for example:
return throwError('callbackResult is false');
}
})
)
}
Update - I thought I'd share some thoughts about why for each step, in case that is helpful. 更新-我以为如果有帮助的话,我会就每个步骤的原因分享一些想法。
initializeRegistration()
will become the source (or outer) observable that kicks things off, and once that completes then renewToken()
will be mapped into the chain and provide the ultimate result as the returned token. initializeRegistration()
将成为可观察到的源(或外部)可观察对象,一旦完成,则renewToken()
将被映射到链中并提供最终结果作为返回的令牌。 return
statement because this function will be all about setting up a single observable chain which is returned and can be subscribed to from the component. return
语句开始,因为此函数将全部用于设置单个可观察的链,该链可返回并可以从组件中进行预订。 initializeRegistration()
. initializeRegistration()
。 After the component subscribes, this function will get executed and the chain will wait to proceed until it completes (or gives an error). initializeRegistration
when it is in turn subscribed to by the component, so we don't need that nested subscribe pattern in your original function. initializeRegistration
时隐式订阅,因此我们在您的原始函数中不需要嵌套的订阅模式。 This operator also maps the new observable (in this case the returned value from renewToken()
into our chain. Therefore we are no longer passing along match
, we are now passing along tokenResult
in the chain. renewToken()
返回的值renewToken()
到我们的链中。因此,我们不再传递match
,而现在传递链中的tokenResult
。 tap
. tap
。 Here is where I really don't understand your business logic and may be wrong in this. renewTokenCallback()
. renewTokenCallback()
。 Depending what that function does this may not be the right way to handle this ... catchError
, this is the check for errors from renewToken()
catchError
,这是检查来自renewToken()
错误的renewToken()
else
- it is important that we return an actual observable from within this else that can be mergeMapped back into the main chain. else
-重要的是,我们返回的实际观察到的从这个别人可以mergeMapped回到主链中。 What that observable should be is unclear to me - some message up to the component to tell it that something went wrong in the callbackResult
callbackResult
出了点问题 I hope this helps. 我希望这有帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.