I have a problem where I want to remove/add any previous added operators of an observable.
I am given the following observable which I cannot change:
let objects$ = of([{
category: 1,
name: 'Some1'
}, {
category: 2,
name: 'Some2'
}]).pipe(
map(o => o.filter(b => b.category === 2))
)
objects$.subscribe(obj => console.log(obj));
This outputs: {category: 2,name: 'Some2'}
as expected.
Now I want to change the value of the filter to b.category === 1
to output {category: 1,name: 'Some1'}
.
If I do the following:
objects$.pipe(
map(o => o.filter(b => b.category === 1))
)
objects$.subscribe(obj => console.log(obj));
I still get {category: 2,name: 'Some2'}
.
If I do:
objects$ = objects$.pipe(
map(o => o.filter(b => b.category === 1))
)
objects$.subscribe(obj => console.log(obj));
I get []
because the output of the observable does not have category 1 anymore.
The question I have is how do I remove the .pipe()
from the original observable to add a new one ?
The async pipe subscribes to an Observable or Promise and returns the latest value it has emitted.
To trigger an element deletion, simply send an event on the subject: this. deleteSubject. next({op:'delete', id: '1'});
To avoid nested subscribe calls you can always map back from a meta branch, such as a stream that has been forked from the main branch through some AJAX call or some other async operation, to a trunk branch by using mergeMap .
The pipe() function takes one or more operators and returns an RxJS Observable. pipe can be used as a standalone method, which helps Angular developers reuse it at multiple places or as an instance method. This article will explain what pipe is and how to use it in an Angular Application.
By using pipe
e.g. calling observable$.pipe( map(..) )
you're not really adding something to the observable$
that can be taken away later on, even if the phrase add operator X to your observable
is quiet often used.
A pipeable Operator is a function that takes an Observable as its input and returns another Observable. It is a pure operation: the previous Observable stays unmodified
const o1$ = of('1');
const o2$ = o1$.pipe(
map(x => x + '2'),
map(x => x + '3')
);
is equivalent to
const o1$ = of('1');
const o2$ = map(x => x + '3')(
map(x => x + '2')(
o1$
)
);
You're basically chaining pure function calls with your original Observable o1$
as input and some other Observable as output. o1$
won't be changed so you have to assign the returned value to a variable (o2$
) to use later on or use it directly to have any effect.
In the example above you could reuse o1$
and create a different Observable than o2$
by using different operators on o1$
. You can't however remove the function calls that are used to define o2$
from o2$
.
If you're given an Observable you cannot change you shouldn't be concerned with it's specific implementation but only with what it emits. In this case the Observable is a black box to you and as far as you know just emits { category: 2, name: 'Some2' }
. You don't know and shouldn't care about specific things the Observable did along the way to emit this value.
BUT you seem to know and care about what the Observable did before emitting this value. If you do, there has to be a way for you (or a colleague) to change the implementation of the Observable.
If you have code where one part should be fixed and another part should be dynamic you can define a higher order function (fixed part) that accepts another function (dynamic part) as input and create different Observables from one original Observable this way:
let getObjects$ = (predicate: (value: any) => boolean) => of([
{
category: 1,
name: "Some1"
},
{
category: 2,
name: "Some2"
}
]).pipe(map(o => o.filter(predicate)));
getObjects$(v => v.category === 1).subscribe(obj => console.log(obj));
getObjects$(v => v.category === 2).subscribe(obj => console.log(obj));
You are applying pipe operator in the first operation (objects$
=> Observable.pipe()
).
After first operation, objects$
inner value will be:
[{category: 2,name: 'Some2'}]
Then your second operation will be done on the result of first one(Observable.pipe(...).pipe(...)
). It will not change the value of objects$
.
But you're again subscribing the initial observable (objects$
=> Observable.pipe()
).
The second pipe will not mutate the value, instead returns new Observable
after applying pipe
operator function.
For the desired result:
let objects$ = of([
{
category: 1,
name: "Some1"
},
{
category: 2,
name: "Some2"
}
]);
objects$
.pipe(map(o => o.filter(b => b.category === 1)))
.subscribe(obj => console.log(obj));
objects$
.pipe(map(o => o.filter(b => b.category === 2)))
.subscribe(obj => console.log(obj));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With