UNPKG

@reactivex/rxjs

Version:

Reactive Extensions for modern JavaScript

1,358 lines (1,322 loc) 483 kB
/*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ /* global global, define, System, Reflect, Promise */ var __extends; var __assign; var __decorate; var __param; var __metadata; var __awaiter; (function (factory) { var root = typeof global === "object" ? global : typeof self === "object" ? self : typeof this === "object" ? this : {}; if (typeof System === "object" && typeof System.register === "function") { System.register("tslib", [], function (exporter) { factory(createExporter(root, exporter)); return { setters: [], execute: function() { } }; }); } else if (typeof define === "function" && define.amd) { define("tslib", ["exports"], function (exports) { factory(createExporter(root, createExporter(exports))); }); } else if (typeof module === "object" && typeof module.exports === "object") { factory(createExporter(root, createExporter(module.exports))); } else { factory(createExporter(root)); } function createExporter(exports, previous) { return function (id, v) { return exports[id] = previous ? previous(id, v) : v; }; } }) (function (exporter) { __extends = function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; __assign = Object.assign || function (t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; __decorate = function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; __param = function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; __metadata = function (metadataKey, metadataValue) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); }; __awaiter = function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments)).next()); }); }; exporter("__extends", __extends); exporter("__assign", __assign); exporter("__decorate", __decorate); exporter("__param", __param); exporter("__metadata", __metadata); exporter("__awaiter", __awaiter); });(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.Rx = global.Rx || {}))); }(this, (function (exports) { 'use strict'; /** * window: browser in DOM main thread * self: browser in WebWorker * global: Node.js/other */ var root = (typeof window == 'object' && window.window === window && window || typeof self == 'object' && self.self === self && self || typeof global == 'object' && global.global === global && global); if (!root) { throw new Error('RxJS could not find any global context (window, self, global)'); } function isFunction(x) { return typeof x === 'function'; } var isArray = Array.isArray || (function (x) { return x && typeof x.length === 'number'; }); function isObject(x) { return x != null && typeof x === 'object'; } // typeof any so that it we don't have to cast when comparing a result to the error object var errorObject = { e: {} }; var tryCatchTarget; function tryCatcher() { try { return tryCatchTarget.apply(this, arguments); } catch (e) { errorObject.e = e; return errorObject; } } function tryCatch(fn) { tryCatchTarget = fn; return tryCatcher; } /** * An error thrown when one or more errors have occurred during the * `unsubscribe` of a {@link Subscription}. */ var UnsubscriptionError = (function (_super) { __extends(UnsubscriptionError, _super); function UnsubscriptionError(errors) { _super.call(this); this.errors = errors; var err = Error.call(this, errors ? errors.length + " errors occurred during unsubscription:\n " + errors.map(function (err, i) { return ((i + 1) + ") " + err.toString()); }).join('\n ') : ''); this.name = err.name = 'UnsubscriptionError'; this.stack = err.stack; this.message = err.message; } return UnsubscriptionError; }(Error)); /** * Represents a disposable resource, such as the execution of an Observable. A * Subscription has one important method, `unsubscribe`, that takes no argument * and just disposes the resource held by the subscription. * * Additionally, subscriptions may be grouped together through the `add()` * method, which will attach a child Subscription to the current Subscription. * When a Subscription is unsubscribed, all its children (and its grandchildren) * will be unsubscribed as well. * * @class Subscription */ var Subscription = (function () { /** * @param {function(): void} [unsubscribe] A function describing how to * perform the disposal of resources when the `unsubscribe` method is called. */ function Subscription(unsubscribe) { /** * A flag to indicate whether this Subscription has already been unsubscribed. * @type {boolean} */ this.closed = false; if (unsubscribe) { this._unsubscribe = unsubscribe; } } /** * Disposes the resources held by the subscription. May, for instance, cancel * an ongoing Observable execution or cancel any other type of work that * started when the Subscription was created. * @return {void} */ Subscription.prototype.unsubscribe = function () { var hasErrors = false; var errors; if (this.closed) { return; } this.closed = true; var _a = this, _unsubscribe = _a._unsubscribe, _subscriptions = _a._subscriptions; this._subscriptions = null; if (isFunction(_unsubscribe)) { var trial = tryCatch(_unsubscribe).call(this); if (trial === errorObject) { hasErrors = true; (errors = errors || []).push(errorObject.e); } } if (isArray(_subscriptions)) { var index = -1; var len = _subscriptions.length; while (++index < len) { var sub = _subscriptions[index]; if (isObject(sub)) { var trial = tryCatch(sub.unsubscribe).call(sub); if (trial === errorObject) { hasErrors = true; errors = errors || []; var err = errorObject.e; if (err instanceof UnsubscriptionError) { errors = errors.concat(err.errors); } else { errors.push(err); } } } } } if (hasErrors) { throw new UnsubscriptionError(errors); } }; /** * Adds a tear down to be called during the unsubscribe() of this * Subscription. * * If the tear down being added is a subscription that is already * unsubscribed, is the same reference `add` is being called on, or is * `Subscription.EMPTY`, it will not be added. * * If this subscription is already in an `closed` state, the passed * tear down logic will be executed immediately. * * @param {TeardownLogic} teardown The additional logic to execute on * teardown. * @return {Subscription} Returns the Subscription used or created to be * added to the inner subscriptions list. This Subscription can be used with * `remove()` to remove the passed teardown logic from the inner subscriptions * list. */ Subscription.prototype.add = function (teardown) { if (!teardown || (teardown === Subscription.EMPTY)) { return Subscription.EMPTY; } if (teardown === this) { return this; } var sub = teardown; switch (typeof teardown) { case 'function': sub = new Subscription(teardown); case 'object': if (sub.closed || typeof sub.unsubscribe !== 'function') { break; } else if (this.closed) { sub.unsubscribe(); } else { (this._subscriptions || (this._subscriptions = [])).push(sub); } break; default: throw new Error('unrecognized teardown ' + teardown + ' added to Subscription.'); } return sub; }; /** * Removes a Subscription from the internal list of subscriptions that will * unsubscribe during the unsubscribe process of this Subscription. * @param {Subscription} subscription The subscription to remove. * @return {void} */ Subscription.prototype.remove = function (subscription) { // HACK: This might be redundant because of the logic in `add()` if (subscription == null || (subscription === this) || (subscription === Subscription.EMPTY)) { return; } var subscriptions = this._subscriptions; if (subscriptions) { var subscriptionIndex = subscriptions.indexOf(subscription); if (subscriptionIndex !== -1) { subscriptions.splice(subscriptionIndex, 1); } } }; Subscription.EMPTY = (function (empty) { empty.closed = true; return empty; }(new Subscription())); return Subscription; }()); var empty = { closed: true, next: function (value) { }, error: function (err) { throw err; }, complete: function () { } }; var Symbol$1 = root.Symbol; var $$rxSubscriber = (typeof Symbol$1 === 'function' && typeof Symbol$1.for === 'function') ? Symbol$1.for('rxSubscriber') : '@@rxSubscriber'; /** * Implements the {@link Observer} interface and extends the * {@link Subscription} class. While the {@link Observer} is the public API for * consuming the values of an {@link Observable}, all Observers get converted to * a Subscriber, in order to provide Subscription-like capabilities such as * `unsubscribe`. Subscriber is a common type in RxJS, and crucial for * implementing operators, but it is rarely used as a public API. * * @class Subscriber<T> */ var Subscriber = (function (_super) { __extends(Subscriber, _super); /** * @param {Observer|function(value: T): void} [destinationOrNext] A partially * defined Observer or a `next` callback function. * @param {function(e: ?any): void} [error] The `error` callback of an * Observer. * @param {function(): void} [complete] The `complete` callback of an * Observer. */ function Subscriber(destinationOrNext, error, complete) { _super.call(this); this.syncErrorValue = null; this.syncErrorThrown = false; this.syncErrorThrowable = false; this.isStopped = false; switch (arguments.length) { case 0: this.destination = empty; break; case 1: if (!destinationOrNext) { this.destination = empty; break; } if (typeof destinationOrNext === 'object') { if (destinationOrNext instanceof Subscriber) { this.destination = destinationOrNext; this.destination.add(this); } else { this.syncErrorThrowable = true; this.destination = new SafeSubscriber(this, destinationOrNext); } break; } default: this.syncErrorThrowable = true; this.destination = new SafeSubscriber(this, destinationOrNext, error, complete); break; } } Subscriber.prototype[$$rxSubscriber] = function () { return this; }; /** * A static factory for a Subscriber, given a (potentially partial) definition * of an Observer. * @param {function(x: ?T): void} [next] The `next` callback of an Observer. * @param {function(e: ?any): void} [error] The `error` callback of an * Observer. * @param {function(): void} [complete] The `complete` callback of an * Observer. * @return {Subscriber<T>} A Subscriber wrapping the (partially defined) * Observer represented by the given arguments. */ Subscriber.create = function (next, error, complete) { var subscriber = new Subscriber(next, error, complete); subscriber.syncErrorThrowable = false; return subscriber; }; /** * The {@link Observer} callback to receive notifications of type `next` from * the Observable, with a value. The Observable may call this method 0 or more * times. * @param {T} [value] The `next` value. * @return {void} */ Subscriber.prototype.next = function (value) { if (!this.isStopped) { this._next(value); } }; /** * The {@link Observer} callback to receive notifications of type `error` from * the Observable, with an attached {@link Error}. Notifies the Observer that * the Observable has experienced an error condition. * @param {any} [err] The `error` exception. * @return {void} */ Subscriber.prototype.error = function (err) { if (!this.isStopped) { this.isStopped = true; this._error(err); } }; /** * The {@link Observer} callback to receive a valueless notification of type * `complete` from the Observable. Notifies the Observer that the Observable * has finished sending push-based notifications. * @return {void} */ Subscriber.prototype.complete = function () { if (!this.isStopped) { this.isStopped = true; this._complete(); } }; Subscriber.prototype.unsubscribe = function () { if (this.closed) { return; } this.isStopped = true; _super.prototype.unsubscribe.call(this); }; Subscriber.prototype._next = function (value) { this.destination.next(value); }; Subscriber.prototype._error = function (err) { this.destination.error(err); this.unsubscribe(); }; Subscriber.prototype._complete = function () { this.destination.complete(); this.unsubscribe(); }; return Subscriber; }(Subscription)); /** * We need this JSDoc comment for affecting ESDoc. * @ignore * @extends {Ignored} */ var SafeSubscriber = (function (_super) { __extends(SafeSubscriber, _super); function SafeSubscriber(_parent, observerOrNext, error, complete) { _super.call(this); this._parent = _parent; var next; var context = this; if (isFunction(observerOrNext)) { next = observerOrNext; } else if (observerOrNext) { context = observerOrNext; next = observerOrNext.next; error = observerOrNext.error; complete = observerOrNext.complete; if (isFunction(context.unsubscribe)) { this.add(context.unsubscribe.bind(context)); } context.unsubscribe = this.unsubscribe.bind(this); } this._context = context; this._next = next; this._error = error; this._complete = complete; } SafeSubscriber.prototype.next = function (value) { if (!this.isStopped && this._next) { var _parent = this._parent; if (!_parent.syncErrorThrowable) { this.__tryOrUnsub(this._next, value); } else if (this.__tryOrSetError(_parent, this._next, value)) { this.unsubscribe(); } } }; SafeSubscriber.prototype.error = function (err) { if (!this.isStopped) { var _parent = this._parent; if (this._error) { if (!_parent.syncErrorThrowable) { this.__tryOrUnsub(this._error, err); this.unsubscribe(); } else { this.__tryOrSetError(_parent, this._error, err); this.unsubscribe(); } } else if (!_parent.syncErrorThrowable) { this.unsubscribe(); throw err; } else { _parent.syncErrorValue = err; _parent.syncErrorThrown = true; this.unsubscribe(); } } }; SafeSubscriber.prototype.complete = function () { if (!this.isStopped) { var _parent = this._parent; if (this._complete) { if (!_parent.syncErrorThrowable) { this.__tryOrUnsub(this._complete); this.unsubscribe(); } else { this.__tryOrSetError(_parent, this._complete); this.unsubscribe(); } } else { this.unsubscribe(); } } }; SafeSubscriber.prototype.__tryOrUnsub = function (fn, value) { try { fn.call(this._context, value); } catch (err) { this.unsubscribe(); throw err; } }; SafeSubscriber.prototype.__tryOrSetError = function (parent, fn, value) { try { fn.call(this._context, value); } catch (err) { parent.syncErrorValue = err; parent.syncErrorThrown = true; return true; } return false; }; SafeSubscriber.prototype._unsubscribe = function () { var _parent = this._parent; this._context = null; this._parent = null; _parent.unsubscribe(); }; return SafeSubscriber; }(Subscriber)); function toSubscriber(nextOrObserver, error, complete) { if (nextOrObserver) { if (nextOrObserver instanceof Subscriber) { return nextOrObserver; } if (nextOrObserver[$$rxSubscriber]) { return nextOrObserver[$$rxSubscriber](); } } if (!nextOrObserver && !error && !complete) { return new Subscriber(empty); } return new Subscriber(nextOrObserver, error, complete); } function getSymbolObservable(context) { var $$observable; var Symbol = context.Symbol; if (typeof Symbol === 'function') { if (Symbol.observable) { $$observable = Symbol.observable; } else { $$observable = Symbol('observable'); Symbol.observable = $$observable; } } else { $$observable = '@@observable'; } return $$observable; } var $$observable = getSymbolObservable(root); /** * A representation of any set of values over any amount of time. This the most basic building block * of RxJS. * * @class Observable<T> */ var Observable = (function () { /** * @constructor * @param {Function} subscribe the function that is called when the Observable is * initially subscribed to. This function is given a Subscriber, to which new values * can be `next`ed, or an `error` method can be called to raise an error, or * `complete` can be called to notify of a successful completion. */ function Observable(subscribe) { this._isScalar = false; if (subscribe) { this._subscribe = subscribe; } } /** * Creates a new Observable, with this Observable as the source, and the passed * operator defined as the new observable's operator. * @method lift * @param {Operator} operator the operator defining the operation to take on the observable * @return {Observable} a new observable with the Operator applied */ Observable.prototype.lift = function (operator) { var observable = new Observable(); observable.source = this; observable.operator = operator; return observable; }; Observable.prototype.subscribe = function (observerOrNext, error, complete) { var operator = this.operator; var sink = toSubscriber(observerOrNext, error, complete); if (operator) { operator.call(sink, this); } else { sink.add(this._subscribe(sink)); } if (sink.syncErrorThrowable) { sink.syncErrorThrowable = false; if (sink.syncErrorThrown) { throw sink.syncErrorValue; } } return sink; }; /** * @method forEach * @param {Function} next a handler for each value emitted by the observable * @param {PromiseConstructor} [PromiseCtor] a constructor function used to instantiate the Promise * @return {Promise} a promise that either resolves on observable completion or * rejects with the handled error */ Observable.prototype.forEach = function (next, PromiseCtor) { var _this = this; if (!PromiseCtor) { if (root.Rx && root.Rx.config && root.Rx.config.Promise) { PromiseCtor = root.Rx.config.Promise; } else if (root.Promise) { PromiseCtor = root.Promise; } } if (!PromiseCtor) { throw new Error('no Promise impl found'); } return new PromiseCtor(function (resolve, reject) { var subscription = _this.subscribe(function (value) { if (subscription) { // if there is a subscription, then we can surmise // the next handling is asynchronous. Any errors thrown // need to be rejected explicitly and unsubscribe must be // called manually try { next(value); } catch (err) { reject(err); subscription.unsubscribe(); } } else { // if there is NO subscription, then we're getting a nexted // value synchronously during subscription. We can just call it. // If it errors, Observable's `subscribe` will ensure the // unsubscription logic is called, then synchronously rethrow the error. // After that, Promise will trap the error and send it // down the rejection path. next(value); } }, reject, resolve); }); }; Observable.prototype._subscribe = function (subscriber) { return this.source.subscribe(subscriber); }; /** * An interop point defined by the es7-observable spec https://github.com/zenparsing/es-observable * @method Symbol.observable * @return {Observable} this instance of the observable */ Observable.prototype[$$observable] = function () { return this; }; // HACK: Since TypeScript inherits static properties too, we have to // fight against TypeScript here so Subject can have a different static create signature /** * Creates a new cold Observable by calling the Observable constructor * @static true * @owner Observable * @method create * @param {Function} subscribe? the subscriber function to be passed to the Observable constructor * @return {Observable} a new cold observable */ Observable.create = function (subscribe) { return new Observable(subscribe); }; return Observable; }()); /** * An error thrown when an action is invalid because the object has been * unsubscribed. * * @see {@link Subject} * @see {@link BehaviorSubject} * * @class ObjectUnsubscribedError */ var ObjectUnsubscribedError = (function (_super) { __extends(ObjectUnsubscribedError, _super); function ObjectUnsubscribedError() { var err = _super.call(this, 'object unsubscribed'); this.name = err.name = 'ObjectUnsubscribedError'; this.stack = err.stack; this.message = err.message; } return ObjectUnsubscribedError; }(Error)); /** * We need this JSDoc comment for affecting ESDoc. * @ignore * @extends {Ignored} */ var SubjectSubscription = (function (_super) { __extends(SubjectSubscription, _super); function SubjectSubscription(subject, subscriber) { _super.call(this); this.subject = subject; this.subscriber = subscriber; this.closed = false; } SubjectSubscription.prototype.unsubscribe = function () { if (this.closed) { return; } this.closed = true; var subject = this.subject; var observers = subject.observers; this.subject = null; if (!observers || observers.length === 0 || subject.isStopped || subject.closed) { return; } var subscriberIndex = observers.indexOf(this.subscriber); if (subscriberIndex !== -1) { observers.splice(subscriberIndex, 1); } }; return SubjectSubscription; }(Subscription)); /** * @class SubjectSubscriber<T> */ var SubjectSubscriber = (function (_super) { __extends(SubjectSubscriber, _super); function SubjectSubscriber(destination) { _super.call(this, destination); this.destination = destination; } return SubjectSubscriber; }(Subscriber)); /** * @class Subject<T> */ var Subject = (function (_super) { __extends(Subject, _super); function Subject() { _super.call(this); this.observers = []; this.closed = false; this.isStopped = false; this.hasError = false; this.thrownError = null; } Subject.prototype[$$rxSubscriber] = function () { return new SubjectSubscriber(this); }; Subject.prototype.lift = function (operator) { var subject = new AnonymousSubject(this, this); subject.operator = operator; return subject; }; Subject.prototype.next = function (value) { if (this.closed) { throw new ObjectUnsubscribedError(); } if (!this.isStopped) { var observers = this.observers; var len = observers.length; var copy = observers.slice(); for (var i = 0; i < len; i++) { copy[i].next(value); } } }; Subject.prototype.error = function (err) { if (this.closed) { throw new ObjectUnsubscribedError(); } this.hasError = true; this.thrownError = err; this.isStopped = true; var observers = this.observers; var len = observers.length; var copy = observers.slice(); for (var i = 0; i < len; i++) { copy[i].error(err); } this.observers.length = 0; }; Subject.prototype.complete = function () { if (this.closed) { throw new ObjectUnsubscribedError(); } this.isStopped = true; var observers = this.observers; var len = observers.length; var copy = observers.slice(); for (var i = 0; i < len; i++) { copy[i].complete(); } this.observers.length = 0; }; Subject.prototype.unsubscribe = function () { this.isStopped = true; this.closed = true; this.observers = null; }; Subject.prototype._subscribe = function (subscriber) { if (this.closed) { throw new ObjectUnsubscribedError(); } else if (this.hasError) { subscriber.error(this.thrownError); return Subscription.EMPTY; } else if (this.isStopped) { subscriber.complete(); return Subscription.EMPTY; } else { this.observers.push(subscriber); return new SubjectSubscription(this, subscriber); } }; Subject.prototype.asObservable = function () { var observable = new Observable(); observable.source = this; return observable; }; Subject.create = function (destination, source) { return new AnonymousSubject(destination, source); }; return Subject; }(Observable)); /** * @class AnonymousSubject<T> */ var AnonymousSubject = (function (_super) { __extends(AnonymousSubject, _super); function AnonymousSubject(destination, source) { _super.call(this); this.destination = destination; this.source = source; } AnonymousSubject.prototype.next = function (value) { var destination = this.destination; if (destination && destination.next) { destination.next(value); } }; AnonymousSubject.prototype.error = function (err) { var destination = this.destination; if (destination && destination.error) { this.destination.error(err); } }; AnonymousSubject.prototype.complete = function () { var destination = this.destination; if (destination && destination.complete) { this.destination.complete(); } }; AnonymousSubject.prototype._subscribe = function (subscriber) { var source = this.source; if (source) { return this.source.subscribe(subscriber); } else { return Subscription.EMPTY; } }; return AnonymousSubject; }(Subject)); /** * @class AsyncSubject<T> */ var AsyncSubject = (function (_super) { __extends(AsyncSubject, _super); function AsyncSubject() { _super.apply(this, arguments); this.value = null; this.hasNext = false; this.hasCompleted = false; } AsyncSubject.prototype._subscribe = function (subscriber) { if (this.hasCompleted && this.hasNext) { subscriber.next(this.value); subscriber.complete(); return Subscription.EMPTY; } else if (this.hasError) { subscriber.error(this.thrownError); return Subscription.EMPTY; } return _super.prototype._subscribe.call(this, subscriber); }; AsyncSubject.prototype.next = function (value) { if (!this.hasCompleted) { this.value = value; this.hasNext = true; } }; AsyncSubject.prototype.complete = function () { this.hasCompleted = true; if (this.hasNext) { _super.prototype.next.call(this, this.value); } _super.prototype.complete.call(this); }; return AsyncSubject; }(Subject)); /** * We need this JSDoc comment for affecting ESDoc. * @extends {Ignored} * @hide true */ var BoundCallbackObservable = (function (_super) { __extends(BoundCallbackObservable, _super); function BoundCallbackObservable(callbackFunc, selector, args, scheduler) { _super.call(this); this.callbackFunc = callbackFunc; this.selector = selector; this.args = args; this.scheduler = scheduler; } /* tslint:enable:max-line-length */ /** * Converts a callback API to a function that returns an Observable. * * <span class="informal">Give it a function `f` of type `f(x, callback)` and * it will return a function `g` that when called as `g(x)` will output an * Observable.</span> * * `bindCallback` is not an operator because its input and output are not * Observables. The input is a function `func` with some parameters, but the * last parameter must be a callback function that `func` calls when it is * done. The output of `bindCallback` is a function that takes the same * parameters as `func`, except the last one (the callback). When the output * function is called with arguments, it will return an Observable where the * results will be delivered to. * * @example <caption>Convert jQuery's getJSON to an Observable API</caption> * // Suppose we have jQuery.getJSON('/my/url', callback) * var getJSONAsObservable = Rx.Observable.bindCallback(jQuery.getJSON); * var result = getJSONAsObservable('/my/url'); * result.subscribe(x => console.log(x), e => console.error(e)); * * @see {@link bindNodeCallback} * @see {@link from} * @see {@link fromPromise} * * @param {function} func Function with a callback as the last parameter. * @param {function} [selector] A function which takes the arguments from the * callback and maps those a value to emit on the output Observable. * @param {Scheduler} [scheduler] The scheduler on which to schedule the * callbacks. * @return {function(...params: *): Observable} A function which returns the * Observable that delivers the same values the callback would deliver. * @static true * @name bindCallback * @owner Observable */ BoundCallbackObservable.create = function (func, selector, scheduler) { if (selector === void 0) { selector = undefined; } return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i - 0] = arguments[_i]; } return new BoundCallbackObservable(func, selector, args, scheduler); }; }; BoundCallbackObservable.prototype._subscribe = function (subscriber) { var callbackFunc = this.callbackFunc; var args = this.args; var scheduler = this.scheduler; var subject = this.subject; if (!scheduler) { if (!subject) { subject = this.subject = new AsyncSubject(); var handler = function handlerFn() { var innerArgs = []; for (var _i = 0; _i < arguments.length; _i++) { innerArgs[_i - 0] = arguments[_i]; } var source = handlerFn.source; var selector = source.selector, subject = source.subject; if (selector) { var result_1 = tryCatch(selector).apply(this, innerArgs); if (result_1 === errorObject) { subject.error(errorObject.e); } else { subject.next(result_1); subject.complete(); } } else { subject.next(innerArgs.length === 1 ? innerArgs[0] : innerArgs); subject.complete(); } }; // use named function instance to avoid closure. handler.source = this; var result = tryCatch(callbackFunc).apply(this, args.concat(handler)); if (result === errorObject) { subject.error(errorObject.e); } } return subject.subscribe(subscriber); } else { return scheduler.schedule(BoundCallbackObservable.dispatch, 0, { source: this, subscriber: subscriber }); } }; BoundCallbackObservable.dispatch = function (state) { var self = this; var source = state.source, subscriber = state.subscriber; var callbackFunc = source.callbackFunc, args = source.args, scheduler = source.scheduler; var subject = source.subject; if (!subject) { subject = source.subject = new AsyncSubject(); var handler = function handlerFn() { var innerArgs = []; for (var _i = 0; _i < arguments.length; _i++) { innerArgs[_i - 0] = arguments[_i]; } var source = handlerFn.source; var selector = source.selector, subject = source.subject; if (selector) { var result_2 = tryCatch(selector).apply(this, innerArgs); if (result_2 === errorObject) { self.add(scheduler.schedule(dispatchError, 0, { err: errorObject.e, subject: subject })); } else { self.add(scheduler.schedule(dispatchNext, 0, { value: result_2, subject: subject })); } } else { var value = innerArgs.length === 1 ? innerArgs[0] : innerArgs; self.add(scheduler.schedule(dispatchNext, 0, { value: value, subject: subject })); } }; // use named function to pass values in without closure handler.source = source; var result = tryCatch(callbackFunc).apply(this, args.concat(handler)); if (result === errorObject) { subject.error(errorObject.e); } } self.add(subject.subscribe(subscriber)); }; return BoundCallbackObservable; }(Observable)); function dispatchNext(arg) { var value = arg.value, subject = arg.subject; subject.next(value); subject.complete(); } function dispatchError(arg) { var err = arg.err, subject = arg.subject; subject.error(err); } var bindCallback = BoundCallbackObservable.create; Observable.bindCallback = bindCallback; /** * We need this JSDoc comment for affecting ESDoc. * @extends {Ignored} * @hide true */ var BoundNodeCallbackObservable = (function (_super) { __extends(BoundNodeCallbackObservable, _super); function BoundNodeCallbackObservable(callbackFunc, selector, args, scheduler) { _super.call(this); this.callbackFunc = callbackFunc; this.selector = selector; this.args = args; this.scheduler = scheduler; } /* tslint:enable:max-line-length */ /** * Converts a Node.js-style callback API to a function that returns an * Observable. * * <span class="informal">It's just like {@link bindCallback}, but the * callback is expected to be of type `callback(error, result)`.</span> * * `bindNodeCallback` is not an operator because its input and output are not * Observables. The input is a function `func` with some parameters, but the * last parameter must be a callback function that `func` calls when it is * done. The callback function is expected to follow Node.js conventions, * where the first argument to the callback is an error, while remaining * arguments are the callback result. The output of `bindNodeCallback` is a * function that takes the same parameters as `func`, except the last one (the * callback). When the output function is called with arguments, it will * return an Observable where the results will be delivered to. * * @example <caption>Read a file from the filesystem and get the data as an Observable</caption> * import * as fs from 'fs'; * var readFileAsObservable = Rx.Observable.bindNodeCallback(fs.readFile); * var result = readFileAsObservable('./roadNames.txt', 'utf8'); * result.subscribe(x => console.log(x), e => console.error(e)); * * @see {@link bindCallback} * @see {@link from} * @see {@link fromPromise} * * @param {function} func Function with a callback as the last parameter. * @param {function} [selector] A function which takes the arguments from the * callback and maps those a value to emit on the output Observable. * @param {Scheduler} [scheduler] The scheduler on which to schedule the * callbacks. * @return {function(...params: *): Observable} A function which returns the * Observable that delivers the same values the Node.js callback would * deliver. * @static true * @name bindNodeCallback * @owner Observable */ BoundNodeCallbackObservable.create = function (func, selector, scheduler) { if (selector === void 0) { selector = undefined; } return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i - 0] = arguments[_i]; } return new BoundNodeCallbackObservable(func, selector, args, scheduler); }; }; BoundNodeCallbackObservable.prototype._subscribe = function (subscriber) { var callbackFunc = this.callbackFunc; var args = this.args; var scheduler = this.scheduler; var subject = this.subject; if (!scheduler) { if (!subject) { subject = this.subject = new AsyncSubject(); var handler = function handlerFn() { var innerArgs = []; for (var _i = 0; _i < arguments.length; _i++) { innerArgs[_i - 0] = arguments[_i]; } var source = handlerFn.source; var selector = source.selector, subject = source.subject; var err = innerArgs.shift(); if (err) { subject.error(err); } else if (selector) { var result_1 = tryCatch(selector).apply(this, innerArgs); if (result_1 === errorObject) { subject.error(errorObject.e); } else { subject.next(result_1); subject.complete(); } } else { subject.next(innerArgs.length === 1 ? innerArgs[0] : innerArgs); subject.complete(); } }; // use named function instance to avoid closure. handler.source = this; var result = tryCatch(callbackFunc).apply(this, args.concat(handler)); if (result === errorObject) { subject.error(errorObject.e); } } return subject.subscribe(subscriber); } else { return scheduler.schedule(dispatch, 0, { source: this, subscriber: subscriber }); } }; return BoundNodeCallbackObservable; }(Observable)); function dispatch(state) { var self = this; var source = state.source, subscriber = state.subscriber; // XXX: cast to `any` to access to the private field in `source`. var _a = source, callbackFunc = _a.callbackFunc, args = _a.args, scheduler = _a.scheduler; var subject = source.subject; if (!subject) { subject = source.subject = new AsyncSubject(); var handler = function handlerFn() { var innerArgs = []; for (var _i = 0; _i < arguments.length; _i++) { innerArgs[_i - 0] = arguments[_i]; } var source = handlerFn.source; var selector = source.selector, subject = source.subject; var err = innerArgs.shift(); if (err) { subject.error(err); } else if (selector) { var result_2 = tryCatch(selector).apply(this, innerArgs); if (result_2 === errorObject) { self.add(scheduler.schedule(dispatchError$1, 0, { err: errorObject.e, subject: subject })); } else { self.add(scheduler.schedule(dispatchNext$1, 0, { value: result_2, subject: subject })); } } else { var value = innerArgs.length === 1 ? innerArgs[0] : innerArgs; self.add(scheduler.schedule(dispatchNext$1, 0, { value: value, subject: subject })); } }; // use named function to pass values in without closure handler.source = source; var result = tryCatch(callbackFunc).apply(this, args.concat(handler)); if (result === errorObject) { subject.error(errorObject.e); } } self.add(subject.subscribe(subscriber)); } function dispatchNext$1(arg) { var value = arg.value, subject = arg.subject; subject.next(value); subject.complete(); } function dispatchError$1(arg) { var err = arg.err, subject = arg.subject; subject.error(err); } var bindNodeCallback = BoundNodeCallbackObservable.create; Observable.bindNodeCallback = bindNodeCallback; function isScheduler(value) { return value && typeof value.schedule === 'function'; } /** * We need this JSDoc comment for affecting ESDoc. * @extends {Ignored} * @hide true */ var ScalarObservable = (function (_super) { __extends(ScalarObservable, _super); function ScalarObservable(value, scheduler) { _super.call(this); this.value = value; this.scheduler = scheduler; this._isScalar = true; if (scheduler) { this._isScalar = false; } } ScalarObservable.create = function (value, scheduler) { return new ScalarObservable(value, scheduler); }; ScalarObservable.dispatch = function (state) { var done = state.done, value = state.value, subscriber = state.subscriber; if (done) { subscriber.complete(); return; } subscriber.next(value); if (subscriber.closed) { return; } state.done = true; this.schedule(state); }; ScalarObservable.prototype._subscribe = function (subscriber) { var value = this.value; var scheduler = this.scheduler; if (scheduler) { return scheduler.schedule(ScalarObservable.dispatch, 0, { done: false, value: value, subscriber: subscriber }); } else { subscriber.next(value); if (!subscriber.closed) { subscriber.complete(); } } }; return ScalarObservable; }(Observable)); /** * We need this JSDoc comment for affecting ESDoc. * @extends {Ignored} * @hide true */ var EmptyObservable = (function (_super) { __extends(EmptyObservable, _super); function EmptyObservable(scheduler) { _super.call(this); this.scheduler = scheduler; } /** * Creates an Observable that emits no items to the Observer and immediately * emits a complete notification. * * <span class="informal">Just emits 'complete', and nothing else. * </span> * * <img src="./img/empty.png" width="100%"> * * This static operator is useful for creating a simple Observable that only * emits the complete notification. It can be used for composing with other * Observables, such as in a {@link mergeMap}. * * @example <caption>Emit the number 7, then complete.</caption> * var result = Rx.Observable.empty().startWith(7); * result.subscribe(x => console.log(x)); * * @example <caption>Map and flatten only odd numbers to the sequence 'a', 'b', 'c'</caption> * var interval = Rx.Observable.interval(1000); * var result = interval.mergeMap(x => * x % 2 === 1 ? Rx.Observable.of('a', 'b', 'c') : Rx.Observable.empty() * ); * result.subscribe(x => console.log(x)); * * @see {@link create} * @see {@link never} * @see {@link of}