我需要知道引发错误后如何保留订阅。
我创建了这个可观察的对象:
let saveClick$ = Observable.fromEvent(this.saveButton.nativeElement, 'click');
因此,我尝试使用Observable.empty
,但据我所知,它发出了一个完整的消息,因此将删除订阅者:
this.saved$ = saveClick$.pipe(this.pushUser(), catchError(() => Observable.empty<AdministrationUser>()), share());
我希望在遇到任何错误时都保留订阅。
有什么想法吗?
其他代码:
// Custom pipes
private push = <T>() => switchMap<T, AdministrationUser>(() => this.service.push(this.user));
private handleError = <T>() => catchError<T, Array<{code: string, message: string}>>((error: ResponseError) => Observable.of(error.errors));
private handleEmptyUser = <T>() => catchError<T, AdministrationUser>(() => Observable.of(UsuarisadministracioSubcomponentComponent.EMPTY_USER));
private pushUser = () => pipe( //simplified pipe
this.push()
);
我的服务是:
const buildURL = () => map((filter: {userId: string} & Trace) => this.buildPushURL(filter.currentUser, filter.currentApplication, filter.userId));
const makeRequest = () => switchMap((url: string) => httpMethodFn.call(this.authHttp, url, user));
const buildResponse = () => map(() => user);
const onErrorGetDetails = () => catchError((error: Response) => Observable.throw(<ResponseError>error.json()));
return Observable.of({userId: user.id})
.pipe(
buildURL(),
makeRequest(),
buildResponse(),
onErrorGetDetails()
);
答案 0 :(得分:1)
您应该在内部可观察的管道中而不是在源可观察的地方捕获错误。如果您在可观察到的源上捕获错误,那么按照rxjs概念,可观察到的源在发生错误后将不会发出新值。因此,像这样在内部可观察的地方捕获错误:
this.saved$ = saveClick$.pipe(
//i am assuming this.pushUser() is a higher order function which returns an observable
this.pushUser()
.pipe(
catchError(() => Observable.empty<AdministrationUser>())
),
share()
);
在内部可观察范围内捕获错误将使您的源可观察活动保持活动状态,即使内部可观察范围引发错误,也将继续发出值。
您可以根据需要移动share()
运算符[即不论是在内部可观测管道内还是在源可观测管道内],但想法仍然相同-在内部可观测管道内捕获错误,以使源(外部)可观测活动保持活跃。
编辑1:[根据用户的最新代码建议简化代码]
请在服务中定义您的push方法,如下所示:
push(user) {
//By seeing your code; I could not figure out where and how are you passing the parameter in buildUrl
//It appears to me that this.buildPushURL method simply return an URL based on the passed parameters and IT DOES NOT MAKE
//ANY HTTP CALL TO YOUR BACKEND. IF THAT IS TRUE -
//THEN please adjust the below code accordingly as I dont know how you use this method OR PLEASE provide some more detaling
//on this.buildPushURL() method
const url = this.buildPushURL(filter.currentUser, filter.currentApplication, filter.userId);
//I am assuming that httpMethodFn calls http.get() or http.post() and returns an observable
//Suggestion - Why you dont use httpClient.get or httpClient.post() directly? It will avoid to call
//httpMethodFn by httpMethodFn.call?
//Bottom line is - httpMethodFn.call must return an observable otherwise adjust your httpMethodFn.call code to return an observable
//to make below code work.
return httpMethodFn.call(this.authHttp, url, user)
.pipe(
map(user => {
console.log(user);
return user;
}),
catchError(error => throwError(<ResponseError>error.json()))
);
}
并像这样使用它-
yourMethodReturnsAnObservableWhichIsSubscribeByTheConsumer() {
const saveClick$ = Observable.fromEvent(this.saveButton.nativeElement, 'click');
return saveClick$.pipe(
switchMap(() => {
return this.push(user)
.pipe(
//you catch error here so that your outer observable will keep alive
//please adjust you code as per your need
//I guess it will give you an idea
handleError()
)
})
);
}
希望您将了解如何简化代码。由于我不了解您的设计和完整的代码,因此我无法提供完美的解决方案。我很确定上面的代码会给您一个想法。
一个建议-最好使用高阶函数,但要理解不要过度使用它们,因为这会使您的代码有点难以理解[PS-这是我个人的观点,并且有不同的观点是很好的。 。:)]。通过应用编码的功能样式,使可观察链尽可能简单。 RXJS很棒:)
答案 1 :(得分:-2)
您需要使用catchError运算符并返回NEVER Observable
import { NEVER } from 'rxjs';
import { catchError } from 'rxjs/operators';
observable$.pipe(catchError((error: any) => {return NEVER;}));