Angular rxjs:达到错误后保持订阅

Jor*_*rdi 5 rxjs typescript angular

我需要知道如何在抛出错误后保持订阅。

我创建了这个可观察的:

let saveClick$ = Observable.fromEvent(this.saveButton.nativeElement, 'click');
Run Code Online (Sandbox Code Playgroud)

所以,我尝试过Observable.empty,但到目前为止我已经能够弄清楚它会发出完整的,因此订阅者将被删除:

this.saved$ = saveClick$.pipe(this.pushUser(), catchError(() => Observable.empty<AdministrationUser>()), share());
Run Code Online (Sandbox Code Playgroud)

我希望当出现任何错误时,订阅被保留。

有任何想法吗?

附加代码:

// 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()
);
Run Code Online (Sandbox Code Playgroud)

而我的服务是:

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()
    );
Run Code Online (Sandbox Code Playgroud)

use*_*584 5

您应该在内部可观察管道而不是源可观察管道中捕获错误。如果您在源 observable 上捕获错误,那么根据 rxjs 概念,源 observable 在发生错误后不会发出新值。因此,捕获内部可观察的错误,如下所示:

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()
                                    );
Run Code Online (Sandbox Code Playgroud)

捕获内部可观察量中的错误将使您的源可观察量保持活动状态,并且即使您的内部可观察量抛出错误,它也会继续发出值。您可以share()根据需要移动运算符[即在内部可观察对象内部或在源可观察对象管道中],但想法保持不变 - 捕获内部可观察对象管道内的错误以保持源(外部)可观察对象处于活动状态。

编辑1:[根据用户的最新代码建议简化代码]

请在您的服务中定义您的推送方法,如下所示:

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()))
                       );

}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它 -

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()
                            )
            })


    );
}
Run Code Online (Sandbox Code Playgroud)

希望您能了解如何简化代码。我无法提供完美的解决方案,因为我不知道您的设计和完整的代码。我很确定上面的代码会给你一个想法。

一个建议 - 使用高阶函数是很好的,但要明白不要过度使用它们,因为它会让你的代码有点难以理解 [PS - 这是我个人的观点,有不同的意见是件好事..:) ]。通过应用函数式编码风格,使您的可观察链尽可能简单。RXJS 太棒了:)