Search code examples
rxjsobservable

Use an observable from within Observable constructor


I currently have a function returning an observable that looks a bit like this:

public foo<T>(): Observable<T> {
    // Execute some instructions X, Y and Z

    return this.http.get<T>(...);
}

So basically, the function executes some instructions before returning an observable that makes an http call.

My issue is that if I do something like this:

const x$ = foo<Type>();

It won't execute the http call (which is normal because I don't subscribe to the observable), however, it will execute the instructions X, Y and Z.

What I would like is to execute these instructions only when I subscribe to the observable, then emit the values from the http call. So far, what I did is:

public foo<T>(): Observable<T> {
    return new Observable<T>(observer => {
        // Execute some instructions X, Y and Z

        const subscription = this.http.get<T>(...).subscribe(observer);

        return { 
            unsubscribe: subscription.unsubscribe
        }
    }
}

Which works but I feel like something is wrong and that I could do it in a better way.

Is there some recommended way to achieve this?


Solution

  • You can perform your side effects using the tap operator:

    public foo<T>(): Observable<T> {
        return this.http.get<T>(...).pipe(
            tap(response => { 
                // Execute some instructions X, Y and Z
            })
        );
    }
    

    However, the above code will only execute your x, y, z AFTER the http response is received.

    If you need the x, y, z to happen before the http call is made, you could do something like this:

    public foo<T>(): Observable<T> {
        return of(undefined).pipe(
            tap(() => { 
                // Execute some instructions X, Y and Z 
            }),
            switchMap(() => this.http.get<T>(...))
        );
    }
    

    Here we're using of to fabricate an observable that emits undefined, then use switchMap to make the http call and emit the http emission.