https://bigfrontend.dev/problem/implement-Observable-transformation-operators
This is a follow-up on 57. create an Observable.
There are a lot of operators for Observable, if we think of Observable as event stream, then modifying the stream is a common task, transformation operators are useful at this.
In this problem, you are asked to implement map(), as the name indicates, it maps the value to another value thus creating a new event stream.
Here is an example.
const source = Observable.from([1, 2, 3]);
map((x) => x * x)(source) // this transformer doubles numbers and create a new stream
.subscribe(console.log);
// 1
// 4
// 9Observable has pipe() method which could make this more readable.
const source = Observable.from([1, 2, 3]);
source.pipe(map((x) => x * x)).subscribe(console.log);
// 1
// 4
// 9Note Observable is already given for you, no need to create it.
I am asked to write a function called map(). It should take in a function that is going to be called on each value emitted by the source Observable. It should return a function that will receive the source Observable and returns the transformed Observable. The class Observable is provided for me.
In the map function, first I need to return a function which takes in an observable as source and returns the transformed observable.
function map(transform) {
return (sourceObservable) => {
// return transformedObservable
};
}In a observable, the value that the observable emits is going to be passed to subscriber.next(value). Therefore, in order to apply the transform function on each value the source observable emits, I need to wrap the subscriber.next(value):
// store the original subscriber.next
subscriber.next = (value) => {
value = transform(value);
// invoke the original subscriber.next passing
// in the transformed value.
};That means, I need to create a new Observable instance; wrap the subscriber.next(value) in the setup of the new Observable and invoke the source observable subscriber passing in the modified subscriber.
return (sourceObservable) => {
const transformedObservable = new Observable((subscriber) => {
subscriber.next = (value) => {
// ...
};
sourceObservable.subscribe(subscriber);
});
// return transformedObservable
};Return the transformed observable at the end.
/**
* @param {any} input
* @return {(observable: Observable) => Observable}
* returns a function which transform Observable
*/
function map(transform) {
return (source) => {
return new Observable((subscriber) => {
const originalNext = subscriber.next;
subscriber.next = (value) => {
const newValue = transform(value);
originalNext.call(subscriber, newValue);
};
source.subscribe(subscriber);
});
};
}