我们有一个执行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
,它将创建MergeMapOperator
或SwitchMapOperator
的实例,并使用适当的next,complete和error方法。但是,SwitchMapOperator
不会由rxjs库导出。
因此,在创建自己的Subscriber类(它只是MergeMapSubscriber
和SwitchMapSubscriber
的组合之前),我们想知道是否丢失了某些内容。
TL; DR
我们希望有一个运算符,它可以根据源可观察对象的值,使用mergeMap或switchMap展平为新的可观察对象。
答案 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())
)
)
);
}
}
希望有帮助。