The RxJS materialize and dematerialize operators are utility operators. Probably you have not used them anywhere in your code yet. But for sure you have come across them indirectly, e.g., through testing output.
RxJS materialize wraps all notifications
The materialize operator transforms all notifications to next notifications and tags them with the original type. This means that a complete notification is wrapped with a Notification object of kind 'C'
while normal next notifications end up with kind 'N'
as seen below:
const source$ = cold('ab|').pipe(
materialize(),
);
expectObservable(source$).toBe(
'ab(c|)', {
a: new Notification('N', 'a'),
b: new Notification('N', 'b'),
c: new Notification('C'),
}
);
Please note that the stream itself completes. That is why there is a '|'
denoting completion specified in the expected Observable.
RxJS materialize with error notification
Also, error notifications can be transformed and show up with the occurred error in the Notification
object.
const source$ = cold('ab#').pipe(
materialize(),
);
expectObservable(source$).toBe(
'ab(c|)', {
a: new Notification('N', 'a'),
b: new Notification('N', 'b'),
c: new Notification('E', undefined, 'error'),
}
);
One can say that materialize annotates notifications with metadata.
The RxJS dematerialize goes in the other direction
The dematerialize operator reverses the effect of materialize. Hence, if the former operator is applied after the latter, the final emission is the original one:
const source$ = cold('ab|').pipe(
materialize(),
dematerialize(),
);
expectObservable(source$).toBe(
'ab|'
);
This post is part of the RxJS mastery series. As always the code examples can be found on GitHub.