I have a usecase where I want to prevent unexpected duplicate Http calls. I'm wondering if I can have a custom operator which can be used in pipe for any API as shown in below example 1
.
Even better if I can use this operator in Angular's HTTP_INTERCEPTOR as shown in example 2
.
Code for customer operator
class RxJsUtils {
private static readonly inProgress = new Map<string, Observable<unknown>>();
static shareDuplicate<T>(indentifier: string): MonoTypeOperatorFunction<T> {
return (source$: Observable<T>): Observable<T> => {
if (this.inProgress.has(indentifier)) {
console.log(`DUPLICATE :: ${indentifier}`);
} else {
this.inProgress.set(indentifier, source$.pipe(shareReplay(1)));
}
return (this.inProgress.get(indentifier) as Observable<T>).pipe(
finalize(() => this.inProgress.delete(indentifier))
);
};
}
}
Example 1: Usage in individual service call
class MyService {
constructor(private http: HttpClient) {}
create() {
return this.http
.post('some-url', {})
.pipe(RxJsUtils.shareDuplicate('some-url'));
}
}
Example 2: Usage in HTTP_INTERCETOR
class ApiInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<unknown>, next: HttpHandler) {
const { urlWithParams } = request;
return next
.handle(request)
.pipe(RxJsUtils.shareDuplicate(urlWithParams));
}
}
Although I'm able to achieve the desired result as I'm able to prevent duplicate using either of the code. I'm still looking for code review & feedback if I'm missing some corner cases. I'm also seeking some guidance wrt the unit test cases that we can write for these kind of custom rxjs operator.
One more thing which I don't have any clue about is when I try to use this operator for individual api call & in interceptor it doesn't work as expected.
I'm little naive to writing custom operator, Any guidance is highly appreciated.