diff --git a/src/operator/materialize.ts b/src/operator/materialize.ts index 2ea2c4d393..3123d0e910 100644 --- a/src/operator/materialize.ts +++ b/src/operator/materialize.ts @@ -1,7 +1,7 @@ -import { Operator } from '../Operator'; + import { Observable } from '../Observable'; -import { Subscriber } from '../Subscriber'; import { Notification } from '../Notification'; +import { materialize as higherOrder } from '../operators'; /** * Represents all of the notifications from the source Observable as `next` @@ -48,38 +48,5 @@ import { Notification } from '../Notification'; * @owner Observable */ export function materialize(this: Observable): Observable> { - return this.lift(new MaterializeOperator()); -} - -class MaterializeOperator implements Operator> { - call(subscriber: Subscriber>, source: any): any { - return source.subscribe(new MaterializeSubscriber(subscriber)); - } -} - -/** - * We need this JSDoc comment for affecting ESDoc. - * @ignore - * @extends {Ignored} - */ -class MaterializeSubscriber extends Subscriber { - constructor(destination: Subscriber>) { - super(destination); - } - - protected _next(value: T) { - this.destination.next(Notification.createNext(value)); - } - - protected _error(err: any) { - const destination = this.destination; - destination.next(Notification.createError(err)); - destination.complete(); - } - - protected _complete() { - const destination = this.destination; - destination.next(Notification.createComplete()); - destination.complete(); - } + return higherOrder()(this); } diff --git a/src/operators/index.ts b/src/operators/index.ts index d9b911f5cb..d243518afd 100644 --- a/src/operators/index.ts +++ b/src/operators/index.ts @@ -9,6 +9,7 @@ export { dematerialize } from './dematerialize'; export { filter } from './filter'; export { ignoreElements } from './ignoreElements'; export { map } from './map'; +export { materialize } from './materialize'; export { max } from './max'; export { mergeAll } from './mergeAll'; export { mergeMap } from './mergeMap'; diff --git a/src/operators/materialize.ts b/src/operators/materialize.ts new file mode 100644 index 0000000000..82f71e4088 --- /dev/null +++ b/src/operators/materialize.ts @@ -0,0 +1,88 @@ +import { Operator } from '../Operator'; +import { Observable } from '../Observable'; +import { Subscriber } from '../Subscriber'; +import { Notification } from '../Notification'; +import { OperatorFunction } from '../interfaces'; + +/** + * Represents all of the notifications from the source Observable as `next` + * emissions marked with their original types within {@link Notification} + * objects. + * + * Wraps `next`, `error` and `complete` emissions in + * {@link Notification} objects, emitted as `next` on the output Observable. + * + * + * + * + * `materialize` returns an Observable that emits a `next` notification for each + * `next`, `error`, or `complete` emission of the source Observable. When the + * source Observable emits `complete`, the output Observable will emit `next` as + * a Notification of type "complete", and then it will emit `complete` as well. + * When the source Observable emits `error`, the output will emit `next` as a + * Notification of type "error", and then `complete`. + * + * This operator is useful for producing metadata of the source Observable, to + * be consumed as `next` emissions. Use it in conjunction with + * {@link dematerialize}. + * + * @example Convert a faulty Observable to an Observable of Notifications + * var letters = Rx.Observable.of('a', 'b', 13, 'd'); + * var upperCase = letters.map(x => x.toUpperCase()); + * var materialized = upperCase.materialize(); + * materialized.subscribe(x => console.log(x)); + * + * // Results in the following: + * // - Notification {kind: "N", value: "A", error: undefined, hasValue: true} + * // - Notification {kind: "N", value: "B", error: undefined, hasValue: true} + * // - Notification {kind: "E", value: undefined, error: TypeError: + * // x.toUpperCase is not a function at MapSubscriber.letters.map.x + * // [as project] (http://1…, hasValue: false} + * + * @see {@link Notification} + * @see {@link dematerialize} + * + * @return {Observable>} An Observable that emits + * {@link Notification} objects that wrap the original emissions from the source + * Observable with metadata. + * @method materialize + * @owner Observable + */ +export function materialize(): OperatorFunction> { + return function materializeOperatorFunction(source: Observable) { + return source.lift(new MaterializeOperator()); + }; +} + +class MaterializeOperator implements Operator> { + call(subscriber: Subscriber>, source: any): any { + return source.subscribe(new MaterializeSubscriber(subscriber)); + } +} + +/** + * We need this JSDoc comment for affecting ESDoc. + * @ignore + * @extends {Ignored} + */ +class MaterializeSubscriber extends Subscriber { + constructor(destination: Subscriber>) { + super(destination); + } + + protected _next(value: T) { + this.destination.next(Notification.createNext(value)); + } + + protected _error(err: any) { + const destination = this.destination; + destination.next(Notification.createError(err)); + destination.complete(); + } + + protected _complete() { + const destination = this.destination; + destination.next(Notification.createComplete()); + destination.complete(); + } +}