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

Benjamin M picture Benjamin M · Mar 22, 2018 · Viewed 8.7k times · Source

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.

Answer

Picci picture Picci · Mar 22, 2018

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