Search code examples
typescriptrxjsobservablerxjs5subject-observer

Wrap an Observable. Do something before and after each emitted value


I'd like to build a wrapper class, that does something before and after each emitted value of an Observable.

Here's what I came up with:

class Wrapper<T> {
    wrapped$: Observable<T>;

    _dataSubject = new Subject<T>();
    data$ = this._dataSubject.pipe(
        tap(_ => console.log("BEFORE"),
        //
        // map( ??? )
        //
    );

    constructor(wrapped$: Observable<T>) {
        this.wrapped$ = wrapped$.pipe(
            tap(_ => console.log("AFTER")
        );
    }
}

let subject = new Subject<string>();
let wrapper = new Wrapper(subject);
wrapper.data$.subscribe(val => console.log(val));
subject.next("foo")

The console output should be:

BEFORE
foo
AFTER

I can't figure out how to connect the $wrapped Observable with the _dataSubject.

But maybe I'm completely wrong and it needs a different approach.


Solution

  • What about something like this

    import {Observable} from 'rxjs';
    
    export class DoBeforeAfter<T> {
        wrapped$: Observable<T>;
    
    
        constructor(wrapped$: Observable<T>, doFunction: (data: any) => void) {
            this.wrapped$ = Observable.of(null)
                .do(_ => console.log("BEFORE"))
                .switchMap(_ => wrapped$)
                .do(doFunction)
                .do(_ => console.log('AFTER'));
        }
    
    }
    

    to be consumed like this

    const source = Observable.of('NOW');
    const beforeAfter = new DoBeforeAfter(source, data => console.log(data));
    
    beforeAfter.wrapped$.subscribe(
            null,
            error => console.error(error),
            () => console.log('DONE')
    

    )

    It looks a bit cumbersome, but maybe it can help