Rxjs:根据可观察的值,使用mergeMap或switchMap传递管道

时间:2019-03-14 13:45:35

标签: rxjs rxjs6

我们有一个执行http请求的请求服务。 所有请求均实现IRequest接口,该接口包含http方法和execute函数,该函数依次返回另一个可观察到的值。

RequestService有一个重载,它接受一个可观察到的源,并有一个requestfactory,它根据源可观察到的值返回一个IRequest实例。

export interface IRequest<TResponse> {
    __method: string;
    execute(): Observable<TResponse>;
}

class RequestService<TSource, TResponse> {
    public execute(source: Observable<TSource>, requestFactory: (input: TSource) => IRequest<TResponse>): Observable<TResponse> {
        return source.pipe(
            map(x => requestFactory(x)),
            switchMap(x => x.execute()),
        );
    }
}

当然,服务中还有很多事情要做(日志记录,默认错误处理等),但是大多数与该问题无关。

现在,所有这一切都像一个咒语,但是我们要做的是默认情况下将switchMap用于GET请求,并将'mergeMap'用于POST,PUT和DELETE请求。

我们似乎无法正常工作。在工厂创建完IRequest实例后,我们需要对其进行访问,只有在具有源可观察值的情况下才可以访问该实例。但是,在操作员中时,我们将无法再控制switchMap或mergeMap之间的选择。

我们的下一个选择是创建自己的RequestMapOperator,它将创建MergeMapOperatorSwitchMapOperator的实例,并使用适当的next,complete和error方法。但是,SwitchMapOperator不会由rxjs库导出。

因此,在创建自己的Subscriber类(它只是MergeMapSubscriberSwitchMapSubscriber的组合之前),我们想知道是否丢失了某些内容。


TL; DR

我们希望有一个运算符,它可以根据源可观察对象的值,使用mergeMap或switchMap展平为新的可观察对象。

1 个答案:

答案 0 :(得分:0)

您可以使用RXJS iif函数,该函数将条件函数作为第一个参数,并根据返回的值确定要订阅的可观察项。

例如。

class RequestService<TSource, TResponse> {
    public execute(source: Observable<TSource>, requestFactory: (input: TSource) => IRequest<TResponse>): Observable<TResponse> {
        return source.pipe(
            map(x => requestFactory(x)),
            // using mergemap outside because we don't want to cancel inner 
            // observable
            margeMap((x) => 
              iif(() => x.method === "GET", 
               switchMap(x => x.execute()),
               margeMap(x => x.execute())
              )
            )
        );
    }
}

希望有帮助。