Search code examples
angularrxjses6-promise

Squashing Promise<Observable<HttpEvent<any>>> to Observable<HttpEvent<any>>


A given Angular HTTP Interceptor must implement

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>

The returned Observable<HttpEvent<any>> usually is the product of next.handle(req) (after - perhaps - modifying the request somehow).

In my case, I need to set some headers, but to find which headers, internally I need to invoke some methods that return Promises. Like this:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  const req1: Promise<HttpRequest<unknown>> = this.service.getFutureValue().then(value => {
    const headers = req.headers.append('X-Custom-Header', value);
    return req.clone({headers});
  });
  ...
}

I need to chain next using req1:

const x = req1.then(r => next.handle(r));

Now I have a Promise<Observable<HttpEvent<any>>>, but I need to somehow transform it to Observable<HttpEvent<any>>.

Conceptually I think this is somehow valid, given that both Promises and Observables are future values.

I'm pretty sure this is a simple transformation, but I don't see how.

EDIT

This may work: from(x).pipe(mergeAll()). But I'll keep looking for something more readable.


Solution

  • How about the following:

    return from(this.service.getFutureValue())
      .pipe(
        mergeMap(x => {
          const headers = req.headers.append('X-Custom-Header', x);
          return next.handle(req.clone({ headers }));
        })
      )
    

    Or optionally:

    return from(this.service.getFutureValue())
      .pipe(
        map(x => {
          const headers = req.headers.append('X-Custom-Header', x);
          return req.clone({ headers });
        }),
        mergeMap(next.handle)
      )