Every new change

This commit is contained in:
Luca Schwan
2020-03-25 11:05:34 +01:00
parent ff8491e75f
commit b4d041c5de
7164 changed files with 499221 additions and 135 deletions

View File

@ -0,0 +1,182 @@
import { Subject, SubjectSubscriber } from '../Subject';
import { Operator } from '../Operator';
import { Observable } from '../Observable';
import { Subscriber } from '../Subscriber';
import { Subscription } from '../Subscription';
import { TeardownLogic } from '../types';
import { refCount as higherOrderRefCount } from '../operators/refCount';
/**
* @class ConnectableObservable<T>
*/
export class ConnectableObservable<T> extends Observable<T> {
protected _subject: Subject<T>;
protected _refCount: number = 0;
protected _connection: Subscription;
/** @internal */
_isComplete = false;
constructor(public source: Observable<T>,
protected subjectFactory: () => Subject<T>) {
super();
}
/** @deprecated This is an internal implementation detail, do not use. */
_subscribe(subscriber: Subscriber<T>) {
return this.getSubject().subscribe(subscriber);
}
protected getSubject(): Subject<T> {
const subject = this._subject;
if (!subject || subject.isStopped) {
this._subject = this.subjectFactory();
}
return this._subject;
}
connect(): Subscription {
let connection = this._connection;
if (!connection) {
this._isComplete = false;
connection = this._connection = new Subscription();
connection.add(this.source
.subscribe(new ConnectableSubscriber(this.getSubject(), this)));
if (connection.closed) {
this._connection = null;
connection = Subscription.EMPTY;
}
}
return connection;
}
refCount(): Observable<T> {
return higherOrderRefCount()(this) as Observable<T>;
}
}
export const connectableObservableDescriptor: PropertyDescriptorMap = (() => {
const connectableProto = <any>ConnectableObservable.prototype;
return {
operator: { value: null as null },
_refCount: { value: 0, writable: true },
_subject: { value: null as null, writable: true },
_connection: { value: null as null, writable: true },
_subscribe: { value: connectableProto._subscribe },
_isComplete: { value: connectableProto._isComplete, writable: true },
getSubject: { value: connectableProto.getSubject },
connect: { value: connectableProto.connect },
refCount: { value: connectableProto.refCount }
};
})();
class ConnectableSubscriber<T> extends SubjectSubscriber<T> {
constructor(destination: Subject<T>,
private connectable: ConnectableObservable<T>) {
super(destination);
}
protected _error(err: any): void {
this._unsubscribe();
super._error(err);
}
protected _complete(): void {
this.connectable._isComplete = true;
this._unsubscribe();
super._complete();
}
protected _unsubscribe() {
const connectable = <any>this.connectable;
if (connectable) {
this.connectable = null;
const connection = connectable._connection;
connectable._refCount = 0;
connectable._subject = null;
connectable._connection = null;
if (connection) {
connection.unsubscribe();
}
}
}
}
class RefCountOperator<T> implements Operator<T, T> {
constructor(private connectable: ConnectableObservable<T>) {
}
call(subscriber: Subscriber<T>, source: any): TeardownLogic {
const { connectable } = this;
(<any> connectable)._refCount++;
const refCounter = new RefCountSubscriber(subscriber, connectable);
const subscription = source.subscribe(refCounter);
if (!refCounter.closed) {
(<any> refCounter).connection = connectable.connect();
}
return subscription;
}
}
class RefCountSubscriber<T> extends Subscriber<T> {
private connection: Subscription;
constructor(destination: Subscriber<T>,
private connectable: ConnectableObservable<T>) {
super(destination);
}
protected _unsubscribe() {
const { connectable } = this;
if (!connectable) {
this.connection = null;
return;
}
this.connectable = null;
const refCount = (<any> connectable)._refCount;
if (refCount <= 0) {
this.connection = null;
return;
}
(<any> connectable)._refCount = refCount - 1;
if (refCount > 1) {
this.connection = null;
return;
}
///
// Compare the local RefCountSubscriber's connection Subscription to the
// connection Subscription on the shared ConnectableObservable. In cases
// where the ConnectableObservable source synchronously emits values, and
// the RefCountSubscriber's downstream Observers synchronously unsubscribe,
// execution continues to here before the RefCountOperator has a chance to
// supply the RefCountSubscriber with the shared connection Subscription.
// For example:
// ```
// range(0, 10).pipe(
// publish(),
// refCount(),
// take(5),
// ).subscribe();
// ```
// In order to account for this case, RefCountSubscriber should only dispose
// the ConnectableObservable's shared connection Subscription if the
// connection Subscription exists, *and* either:
// a. RefCountSubscriber doesn't have a reference to the shared connection
// Subscription yet, or,
// b. RefCountSubscriber's connection Subscription reference is identical
// to the shared connection Subscription
///
const { connection } = this;
const sharedConnection = (<any> connectable)._connection;
this.connection = null;
if (sharedConnection && (!connection || sharedConnection === connection)) {
sharedConnection.unsubscribe();
}
}
}

View File

@ -0,0 +1,52 @@
import { SchedulerLike, SchedulerAction } from '../types';
import { Subscriber } from '../Subscriber';
import { Subscription } from '../Subscription';
import { Observable } from '../Observable';
import { asap } from '../scheduler/asap';
import { isNumeric } from '../util/isNumeric';
export interface DispatchArg<T> {
source: Observable<T>;
subscriber: Subscriber<T>;
}
/**
* We need this JSDoc comment for affecting ESDoc.
* @extends {Ignored}
* @hide true
*/
export class SubscribeOnObservable<T> extends Observable<T> {
/** @nocollapse */
static create<T>(source: Observable<T>, delay: number = 0, scheduler: SchedulerLike = asap): Observable<T> {
return new SubscribeOnObservable(source, delay, scheduler);
}
/** @nocollapse */
static dispatch<T>(this: SchedulerAction<T>, arg: DispatchArg<T>): Subscription {
const { source, subscriber } = arg;
return this.add(source.subscribe(subscriber));
}
constructor(public source: Observable<T>,
private delayTime: number = 0,
private scheduler: SchedulerLike = asap) {
super();
if (!isNumeric(delayTime) || delayTime < 0) {
this.delayTime = 0;
}
if (!scheduler || typeof scheduler.schedule !== 'function') {
this.scheduler = asap;
}
}
/** @deprecated This is an internal implementation detail, do not use. */
_subscribe(subscriber: Subscriber<T>) {
const delay = this.delayTime;
const source = this.source;
const scheduler = this.scheduler;
return scheduler.schedule<DispatchArg<any>>(SubscribeOnObservable.dispatch, delay, {
source, subscriber
});
}
}

View File

@ -0,0 +1,290 @@
import { SchedulerLike, SchedulerAction } from '../types';
import { Observable } from '../Observable';
import { AsyncSubject } from '../AsyncSubject';
import { Subscriber } from '../Subscriber';
import { map } from '../operators/map';
import { canReportError } from '../util/canReportError';
import { isArray } from '../util/isArray';
import { isScheduler } from '../util/isScheduler';
// tslint:disable:max-line-length
/** @deprecated resultSelector is no longer supported, use a mapping function. */
export function bindCallback(callbackFunc: Function, resultSelector: Function, scheduler?: SchedulerLike): (...args: any[]) => Observable<any>;
export function bindCallback<R1, R2, R3, R4>(callbackFunc: (callback: (res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): () => Observable<any[]>;
export function bindCallback<R1, R2, R3>(callbackFunc: (callback: (res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): () => Observable<[R1, R2, R3]>;
export function bindCallback<R1, R2>(callbackFunc: (callback: (res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): () => Observable<[R1, R2]>;
export function bindCallback<R1>(callbackFunc: (callback: (res1: R1) => any) => any, scheduler?: SchedulerLike): () => Observable<R1>;
export function bindCallback(callbackFunc: (callback: () => any) => any, scheduler?: SchedulerLike): () => Observable<void>;
export function bindCallback<A1, R1, R2, R3, R4>(callbackFunc: (arg1: A1, callback: (res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<any[]>;
export function bindCallback<A1, R1, R2, R3>(callbackFunc: (arg1: A1, callback: (res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<[R1, R2, R3]>;
export function bindCallback<A1, R1, R2>(callbackFunc: (arg1: A1, callback: (res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<[R1, R2]>;
export function bindCallback<A1, R1>(callbackFunc: (arg1: A1, callback: (res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<R1>;
export function bindCallback<A1>(callbackFunc: (arg1: A1, callback: () => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<void>;
export function bindCallback<A1, A2, R1, R2, R3, R4>(callbackFunc: (arg1: A1, arg2: A2, callback: (res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2) => Observable<any[]>;
export function bindCallback<A1, A2, R1, R2, R3>(callbackFunc: (arg1: A1, arg2: A2, callback: (res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2) => Observable<[R1, R2, R3]>;
export function bindCallback<A1, A2, R1, R2>(callbackFunc: (arg1: A1, arg2: A2, callback: (res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2) => Observable<[R1, R2]>;
export function bindCallback<A1, A2, R1>(callbackFunc: (arg1: A1, arg2: A2, callback: (res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2) => Observable<R1>;
export function bindCallback<A1, A2>(callbackFunc: (arg1: A1, arg2: A2, callback: () => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2) => Observable<void>;
export function bindCallback<A1, A2, A3, R1, R2, R3, R4>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, callback: (res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3) => Observable<any[]>;
export function bindCallback<A1, A2, A3, R1, R2, R3>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, callback: (res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3) => Observable<[R1, R2, R3]>;
export function bindCallback<A1, A2, A3, R1, R2>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, callback: (res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3) => Observable<[R1, R2]>;
export function bindCallback<A1, A2, A3, R1>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, callback: (res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3) => Observable<R1>;
export function bindCallback<A1, A2, A3>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, callback: () => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3) => Observable<void>;
export function bindCallback<A1, A2, A3, A4, R1, R2, R3, R4>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4) => Observable<any[]>;
export function bindCallback<A1, A2, A3, A4, R1, R2, R3>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4) => Observable<[R1, R2, R3]>;
export function bindCallback<A1, A2, A3, A4, R1, R2>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4) => Observable<[R1, R2]>;
export function bindCallback<A1, A2, A3, A4, R1>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4) => Observable<R1>;
export function bindCallback<A1, A2, A3, A4>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: () => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4) => Observable<void>;
export function bindCallback<A1, A2, A3, A4, A5, R1, R2, R3, R4>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => Observable<any[]>;
export function bindCallback<A1, A2, A3, A4, A5, R1, R2, R3>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => Observable<[R1, R2, R3]>;
export function bindCallback<A1, A2, A3, A4, A5, R1, R2>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => Observable<[R1, R2]>;
export function bindCallback<A1, A2, A3, A4, A5, R1>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => Observable<R1>;
export function bindCallback<A1, A2, A3, A4, A5>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: () => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => Observable<void>;
export function bindCallback<A, R>(callbackFunc: (...args: Array<A | ((result: R) => any)>) => any, scheduler?: SchedulerLike): (...args: A[]) => Observable<R>;
export function bindCallback<A, R>(callbackFunc: (...args: Array<A | ((...results: R[]) => any)>) => any, scheduler?: SchedulerLike): (...args: A[]) => Observable<R[]>;
export function bindCallback(callbackFunc: Function, scheduler?: SchedulerLike): (...args: any[]) => Observable<any>;
// 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. 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. If function `func`
* calls its callback with one argument, the Observable will emit that value.
* If on the other hand the callback is called with multiple values the resulting
* Observable will emit an array with said values as arguments.
*
* It is **very important** to remember that input function `func` is not called
* when the output function is, but rather when the Observable returned by the output
* function is subscribed. This means if `func` makes an AJAX request, that request
* will be made every time someone subscribes to the resulting Observable, but not before.
*
* The last optional parameter - `scheduler` - can be used to control when the call
* to `func` happens after someone subscribes to Observable, as well as when results
* passed to callback will be emitted. By default, the subscription to an Observable calls `func`
* synchronously, but using {@link asyncScheduler} as the last parameter will defer the call to `func`,
* just like wrapping the call in `setTimeout` with a timeout of `0` would. If you were to use the async Scheduler
* and call `subscribe` on the output Observable, all function calls that are currently executing
* will end before `func` is invoked.
*
* By default, results passed to the callback are emitted immediately after `func` invokes the callback.
* In particular, if the callback is called synchronously, then the subscription of the resulting Observable
* will call the `next` function synchronously as well. If you want to defer that call,
* you may use {@link asyncScheduler} just as before. This means that by using `Scheduler.async` you can
* ensure that `func` always calls its callback asynchronously, thus avoiding terrifying Zalgo.
*
* Note that the Observable created by the output function will always emit a single value
* and then complete immediately. If `func` calls the callback multiple times, values from subsequent
* calls will not appear in the stream. If you need to listen for multiple calls,
* you probably want to use {@link fromEvent} or {@link fromEventPattern} instead.
*
* If `func` depends on some context (`this` property) and is not already bound, the context of `func`
* will be the context that the output function has at call time. In particular, if `func`
* is called as a method of some objec and if `func` is not already bound, in order to preserve the context
* it is recommended that the context of the output function is set to that object as well.
*
* If the input function calls its callback in the "node style" (i.e. first argument to callback is
* optional error parameter signaling whether the call failed or not), {@link bindNodeCallback}
* provides convenient error handling and probably is a better choice.
* `bindCallback` will treat such functions the same as any other and error parameters
* (whether passed or not) will always be interpreted as regular callback argument.
*
* ## Examples
*
* ### Convert jQuery's getJSON to an Observable API
* ```ts
* import { bindCallback } from 'rxjs';
* import * as jQuery from 'jquery';
*
* // Suppose we have jQuery.getJSON('/my/url', callback)
* const getJSONAsObservable = bindCallback(jQuery.getJSON);
* const result = getJSONAsObservable('/my/url');
* result.subscribe(x => console.log(x), e => console.error(e));
* ```
*
* ### Receive an array of arguments passed to a callback
* ```ts
* import { bindCallback } from 'rxjs';
*
* const someFunction = (a, b, c) => {
* console.log(a); // 5
* console.log(b); // 'some string'
* console.log(c); // {someProperty: 'someValue'}
* };
*
* const boundSomeFunction = bindCallback(someFunction);
* boundSomeFunction().subscribe(values => {
* console.log(values) // [5, 'some string', {someProperty: 'someValue'}]
* });
* ```
*
* ### Compare behaviour with and without async Scheduler
* ```ts
* import { bindCallback } from 'rxjs';
*
* function iCallMyCallbackSynchronously(cb) {
* cb();
* }
*
* const boundSyncFn = bindCallback(iCallMyCallbackSynchronously);
* const boundAsyncFn = bindCallback(iCallMyCallbackSynchronously, null, Rx.Scheduler.async);
*
* boundSyncFn().subscribe(() => console.log('I was sync!'));
* boundAsyncFn().subscribe(() => console.log('I was async!'));
* console.log('This happened...');
*
* // Logs:
* // I was sync!
* // This happened...
* // I was async!
* ```
*
* ### Use bindCallback on an object method
* ```ts
* import { bindCallback } from 'rxjs';
*
* const boundMethod = bindCallback(someObject.methodWithCallback);
* boundMethod.call(someObject) // make sure methodWithCallback has access to someObject
* .subscribe(subscriber);
* ```
*
* @see {@link bindNodeCallback}
* @see {@link from}
*
* @param {function} func A function with a callback as the last parameter.
* @param {SchedulerLike} [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.
* @name bindCallback
*/
export function bindCallback<T>(
callbackFunc: Function,
resultSelector?: Function|SchedulerLike,
scheduler?: SchedulerLike
): (...args: any[]) => Observable<T> {
if (resultSelector) {
if (isScheduler(resultSelector)) {
scheduler = resultSelector;
} else {
// DEPRECATED PATH
return (...args: any[]) => bindCallback(callbackFunc, scheduler)(...args).pipe(
map((args) => isArray(args) ? resultSelector(...args) : resultSelector(args)),
);
}
}
return function (this: any, ...args: any[]): Observable<T> {
const context = this;
let subject: AsyncSubject<T>;
const params = {
context,
subject,
callbackFunc,
scheduler,
};
return new Observable<T>(subscriber => {
if (!scheduler) {
if (!subject) {
subject = new AsyncSubject<T>();
const handler = (...innerArgs: any[]) => {
subject.next(innerArgs.length <= 1 ? innerArgs[0] : innerArgs);
subject.complete();
};
try {
callbackFunc.apply(context, [...args, handler]);
} catch (err) {
if (canReportError(subject)) {
subject.error(err);
} else {
console.warn(err);
}
}
}
return subject.subscribe(subscriber);
} else {
const state: DispatchState<T> = {
args, subscriber, params,
};
return scheduler.schedule<DispatchState<T>>(dispatch, 0, state);
}
});
};
}
interface DispatchState<T> {
args: any[];
subscriber: Subscriber<T>;
params: ParamsContext<T>;
}
interface ParamsContext<T> {
callbackFunc: Function;
scheduler: SchedulerLike;
context: any;
subject: AsyncSubject<T>;
}
function dispatch<T>(this: SchedulerAction<DispatchState<T>>, state: DispatchState<T>) {
const self = this;
const { args, subscriber, params } = state;
const { callbackFunc, context, scheduler } = params;
let { subject } = params;
if (!subject) {
subject = params.subject = new AsyncSubject<T>();
const handler = (...innerArgs: any[]) => {
const value = innerArgs.length <= 1 ? innerArgs[0] : innerArgs;
this.add(scheduler.schedule<NextState<T>>(dispatchNext, 0, { value, subject }));
};
try {
callbackFunc.apply(context, [...args, handler]);
} catch (err) {
subject.error(err);
}
}
this.add(subject.subscribe(subscriber));
}
interface NextState<T> {
subject: AsyncSubject<T>;
value: T;
}
function dispatchNext<T>(this: SchedulerAction<NextState<T>>, state: NextState<T>) {
const { value, subject } = state;
subject.next(value);
subject.complete();
}
interface ErrorState<T> {
subject: AsyncSubject<T>;
err: any;
}
function dispatchError<T>(this: SchedulerAction<ErrorState<T>>, state: ErrorState<T>) {
const { err, subject } = state;
subject.error(err);
}

View File

@ -0,0 +1,278 @@
import { Observable } from '../Observable';
import { AsyncSubject } from '../AsyncSubject';
import { Subscriber } from '../Subscriber';
import { SchedulerAction, SchedulerLike } from '../types';
import { map } from '../operators/map';
import { canReportError } from '../util/canReportError';
import { isScheduler } from '../util/isScheduler';
import { isArray } from '../util/isArray';
/* tslint:disable:max-line-length */
/** @deprecated resultSelector is deprecated, pipe to map instead */
export function bindNodeCallback(callbackFunc: Function, resultSelector: Function, scheduler?: SchedulerLike): (...args: any[]) => Observable<any>;
export function bindNodeCallback<R1, R2, R3, R4>(callbackFunc: (callback: (err: any, res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (...args: any[]) => Observable<any[]>;
export function bindNodeCallback<R1, R2, R3>(callbackFunc: (callback: (err: any, res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): () => Observable<[R1, R2, R3]>;
export function bindNodeCallback<R1, R2>(callbackFunc: (callback: (err: any, res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): () => Observable<[R1, R2]>;
export function bindNodeCallback<R1>(callbackFunc: (callback: (err: any, res1: R1) => any) => any, scheduler?: SchedulerLike): () => Observable<R1>;
export function bindNodeCallback(callbackFunc: (callback: (err: any) => any) => any, scheduler?: SchedulerLike): () => Observable<void>;
export function bindNodeCallback<A1, R1, R2, R3, R4>(callbackFunc: (arg1: A1, callback: (err: any, res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (...args: any[]) => Observable<any[]>;
export function bindNodeCallback<A1, R1, R2, R3>(callbackFunc: (arg1: A1, callback: (err: any, res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<[R1, R2, R3]>;
export function bindNodeCallback<A1, R1, R2>(callbackFunc: (arg1: A1, callback: (err: any, res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<[R1, R2]>;
export function bindNodeCallback<A1, R1>(callbackFunc: (arg1: A1, callback: (err: any, res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<R1>;
export function bindNodeCallback<A1>(callbackFunc: (arg1: A1, callback: (err: any) => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<void>;
export function bindNodeCallback<A1, A2, R1, R2, R3, R4>(callbackFunc: (arg1: A1, arg2: A2, callback: (err: any, res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (...args: any[]) => Observable<any[]>;
export function bindNodeCallback<A1, A2, R1, R2, R3>(callbackFunc: (arg1: A1, arg2: A2, callback: (err: any, res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2) => Observable<[R1, R2, R3]>;
export function bindNodeCallback<A1, A2, R1, R2>(callbackFunc: (arg1: A1, arg2: A2, callback: (err: any, res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2) => Observable<[R1, R2]>;
export function bindNodeCallback<A1, A2, R1>(callbackFunc: (arg1: A1, arg2: A2, callback: (err: any, res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2) => Observable<R1>;
export function bindNodeCallback<A1, A2>(callbackFunc: (arg1: A1, arg2: A2, callback: (err: any) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2) => Observable<void>;
export function bindNodeCallback<A1, A2, A3, R1, R2, R3, R4>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, callback: (err: any, res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (...args: any[]) => Observable<any[]>;
export function bindNodeCallback<A1, A2, A3, R1, R2, R3>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, callback: (err: any, res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3) => Observable<[R1, R2, R3]>;
export function bindNodeCallback<A1, A2, A3, R1, R2>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, callback: (err: any, res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3) => Observable<[R1, R2]>;
export function bindNodeCallback<A1, A2, A3, R1>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, callback: (err: any, res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3) => Observable<R1>;
export function bindNodeCallback<A1, A2, A3>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, callback: (err: any) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3) => Observable<void>;
export function bindNodeCallback<A1, A2, A3, A4, R1, R2, R3, R4>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (err: any, res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (...args: any[]) => Observable<any[]>;
export function bindNodeCallback<A1, A2, A3, A4, R1, R2, R3>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (err: any, res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4) => Observable<[R1, R2, R3]>;
export function bindNodeCallback<A1, A2, A3, A4, R1, R2>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (err: any, res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4) => Observable<[R1, R2]>;
export function bindNodeCallback<A1, A2, A3, A4, R1>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (err: any, res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4) => Observable<R1>;
export function bindNodeCallback<A1, A2, A3, A4>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, callback: (err: any) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4) => Observable<void>;
export function bindNodeCallback<A1, A2, A3, A4, A5, R1, R2, R3, R4>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (err: any, res1: R1, res2: R2, res3: R3, res4: R4, ...args: any[]) => any) => any, scheduler?: SchedulerLike): (...args: any[]) => Observable<any[]>;
export function bindNodeCallback<A1, A2, A3, A4, A5, R1, R2, R3>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (err: any, res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => Observable<[R1, R2, R3]>;
export function bindNodeCallback<A1, A2, A3, A4, A5, R1, R2>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (err: any, res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => Observable<[R1, R2]>;
export function bindNodeCallback<A1, A2, A3, A4, A5, R1>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (err: any, res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => Observable<R1>;
export function bindNodeCallback<A1, A2, A3, A4, A5>(callbackFunc: (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5, callback: (err: any) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2, arg3: A3, arg4: A4, arg5: A5) => Observable<void>; /* tslint:enable:max-line-length */
export function bindNodeCallback(callbackFunc: Function, scheduler?: SchedulerLike): (...args: any[]) => Observable<any[]>;
/**
* 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 object, signaling
* whether call was successful. If that object is passed to callback, it means
* something went wrong.
*
* 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.
* If `func` calls its callback with error parameter present, Observable will
* error with that value as well. If error parameter is not passed, Observable will emit
* second parameter. If there are more parameters (third and so on),
* Observable will emit an array with all arguments, except first error argument.
*
* Note that `func` will not be called at the same time output function is,
* but rather whenever resulting Observable is subscribed. By default call to
* `func` will happen synchronously after subscription, but that can be changed
* with proper `scheduler` provided as optional third parameter. {@link SchedulerLike}
* can also control when values from callback will be emitted by Observable.
* To find out more, check out documentation for {@link bindCallback}, where
* {@link SchedulerLike} works exactly the same.
*
* As in {@link bindCallback}, context (`this` property) of input function will be set to context
* of returned function, when it is called.
*
* After Observable emits value, it will complete immediately. This means
* even if `func` calls callback again, values from second and consecutive
* calls will never appear on the stream. If you need to handle functions
* that call callbacks multiple times, check out {@link fromEvent} or
* {@link fromEventPattern} instead.
*
* Note that `bindNodeCallback` can be used in non-Node.js environments as well.
* "Node.js-style" callbacks are just a convention, so if you write for
* browsers or any other environment and API you use implements that callback style,
* `bindNodeCallback` can be safely used on that API functions as well.
*
* Remember that Error object passed to callback does not have to be an instance
* of JavaScript built-in `Error` object. In fact, it does not even have to an object.
* Error parameter of callback function is interpreted as "present", when value
* of that parameter is truthy. It could be, for example, non-zero number, non-empty
* string or boolean `true`. In all of these cases resulting Observable would error
* with that value. This means usually regular style callbacks will fail very often when
* `bindNodeCallback` is used. If your Observable errors much more often then you
* would expect, check if callback really is called in Node.js-style and, if not,
* switch to {@link bindCallback} instead.
*
* Note that even if error parameter is technically present in callback, but its value
* is falsy, it still won't appear in array emitted by Observable.
*
* ## Examples
* ### Read a file from the filesystem and get the data as an Observable
* ```ts
* import * as fs from 'fs';
* const readFileAsObservable = bindNodeCallback(fs.readFile);
* const result = readFileAsObservable('./roadNames.txt', 'utf8');
* result.subscribe(x => console.log(x), e => console.error(e));
* ```
*
* ### Use on function calling callback with multiple arguments
* ```ts
* someFunction((err, a, b) => {
* console.log(err); // null
* console.log(a); // 5
* console.log(b); // "some string"
* });
* const boundSomeFunction = bindNodeCallback(someFunction);
* boundSomeFunction()
* .subscribe(value => {
* console.log(value); // [5, "some string"]
* });
* ```
*
* ### Use on function calling callback in regular style
* ```ts
* someFunction(a => {
* console.log(a); // 5
* });
* const boundSomeFunction = bindNodeCallback(someFunction);
* boundSomeFunction()
* .subscribe(
* value => {} // never gets called
* err => console.log(err) // 5
* );
* ```
*
* @see {@link bindCallback}
* @see {@link from}
*
* @param {function} func Function with a Node.js-style callback as the last parameter.
* @param {SchedulerLike} [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.
* @name bindNodeCallback
*/
export function bindNodeCallback<T>(
callbackFunc: Function,
resultSelector: Function|SchedulerLike,
scheduler?: SchedulerLike
): (...args: any[]) => Observable<T> {
if (resultSelector) {
if (isScheduler(resultSelector)) {
scheduler = resultSelector;
} else {
// DEPRECATED PATH
return (...args: any[]) => bindNodeCallback(callbackFunc, scheduler)(...args).pipe(
map(args => isArray(args) ? resultSelector(...args) : resultSelector(args))
);
}
}
return function(this: any, ...args: any[]): Observable<T> {
const params: ParamsState<T> = {
subject: undefined,
args,
callbackFunc,
scheduler,
context: this,
};
return new Observable<T>(subscriber => {
const { context } = params;
let { subject } = params;
if (!scheduler) {
if (!subject) {
subject = params.subject = new AsyncSubject<T>();
const handler = (...innerArgs: any[]) => {
const err = innerArgs.shift();
if (err) {
subject.error(err);
return;
}
subject.next(innerArgs.length <= 1 ? innerArgs[0] : innerArgs);
subject.complete();
};
try {
callbackFunc.apply(context, [...args, handler]);
} catch (err) {
if (canReportError(subject)) {
subject.error(err);
} else {
console.warn(err);
}
}
}
return subject.subscribe(subscriber);
} else {
return scheduler.schedule<DispatchState<T>>(dispatch, 0, { params, subscriber, context });
}
});
};
}
interface DispatchState<T> {
subscriber: Subscriber<T>;
context: any;
params: ParamsState<T>;
}
interface ParamsState<T> {
callbackFunc: Function;
args: any[];
scheduler: SchedulerLike;
subject: AsyncSubject<T>;
context: any;
}
function dispatch<T>(this: SchedulerAction<DispatchState<T>>, state: DispatchState<T>) {
const { params, subscriber, context } = state;
const { callbackFunc, args, scheduler } = params;
let subject = params.subject;
if (!subject) {
subject = params.subject = new AsyncSubject<T>();
const handler = (...innerArgs: any[]) => {
const err = innerArgs.shift();
if (err) {
this.add(scheduler.schedule<DispatchErrorArg<T>>(dispatchError, 0, { err, subject }));
} else {
const value = innerArgs.length <= 1 ? innerArgs[0] : innerArgs;
this.add(scheduler.schedule<DispatchNextArg<T>>(dispatchNext, 0, { value, subject }));
}
};
try {
callbackFunc.apply(context, [...args, handler]);
} catch (err) {
this.add(scheduler.schedule<DispatchErrorArg<T>>(dispatchError, 0, { err, subject }));
}
}
this.add(subject.subscribe(subscriber));
}
interface DispatchNextArg<T> {
subject: AsyncSubject<T>;
value: T;
}
function dispatchNext<T>(arg: DispatchNextArg<T>) {
const { value, subject } = arg;
subject.next(value);
subject.complete();
}
interface DispatchErrorArg<T> {
subject: AsyncSubject<T>;
err: any;
}
function dispatchError<T>(arg: DispatchErrorArg<T>) {
const { err, subject } = arg;
subject.error(err);
}

View File

@ -0,0 +1,328 @@
import { Observable } from '../Observable';
import { ObservableInput, SchedulerLike, ObservedValueOf } from '../types';
import { isScheduler } from '../util/isScheduler';
import { isArray } from '../util/isArray';
import { Subscriber } from '../Subscriber';
import { OuterSubscriber } from '../OuterSubscriber';
import { Operator } from '../Operator';
import { InnerSubscriber } from '../InnerSubscriber';
import { subscribeToResult } from '../util/subscribeToResult';
import { fromArray } from './fromArray';
const NONE = {};
/* tslint:disable:max-line-length */
// If called with a single array, it "auto-spreads" the array, with result selector
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function combineLatest<O1 extends ObservableInput<any>, R>(sources: [O1], resultSelector: (v1: ObservedValueOf<O1>) => R, scheduler?: SchedulerLike): Observable<R>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, R>(sources: [O1, O2], resultSelector: (v1: ObservedValueOf<O1>, v2: ObservedValueOf<O2>) => R, scheduler?: SchedulerLike): Observable<R>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, R>(sources: [O1, O2, O3], resultSelector: (v1: ObservedValueOf<O1>, v2: ObservedValueOf<O2>, v3: ObservedValueOf<O3>) => R, scheduler?: SchedulerLike): Observable<R>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, R>(sources: [O1, O2, O3, O4], resultSelector: (v1: ObservedValueOf<O1>, v2: ObservedValueOf<O2>, v3: ObservedValueOf<O3>, v4: ObservedValueOf<O4>) => R, scheduler?: SchedulerLike): Observable<R>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>, R>(sources: [O1, O2, O3, O4, O5], resultSelector: (v1: ObservedValueOf<O1>, v2: ObservedValueOf<O2>, v3: ObservedValueOf<O3>, v4: ObservedValueOf<O4>, v5: ObservedValueOf<O5>) => R, scheduler?: SchedulerLike): Observable<R>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>, O6 extends ObservableInput<any>, R>(sources: [O1, O2, O3, O4, O5, O6], resultSelector: (v1: ObservedValueOf<O1>, v2: ObservedValueOf<O2>, v3: ObservedValueOf<O3>, v4: ObservedValueOf<O4>, v5: ObservedValueOf<O5>, v6: ObservedValueOf<O6>) => R, scheduler?: SchedulerLike): Observable<R>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function combineLatest<O extends ObservableInput<any>, R>(sources: O[], resultSelector: (...args: ObservedValueOf<O>[]) => R, scheduler?: SchedulerLike): Observable<R>;
// standard call, but with a result selector
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function combineLatest<O1 extends ObservableInput<any>, R>(v1: O1, resultSelector: (v1: ObservedValueOf<O1>) => R, scheduler?: SchedulerLike): Observable<R>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, R>(v1: O1, v2: O2, resultSelector: (v1: ObservedValueOf<O1>, v2: ObservedValueOf<O2>) => R, scheduler?: SchedulerLike): Observable<R>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, R>(v1: O1, v2: O2, v3: O3, resultSelector: (v1: ObservedValueOf<O1>, v2: ObservedValueOf<O2>, v3: ObservedValueOf<O3>) => R, scheduler?: SchedulerLike): Observable<R>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, R>(v1: O1, v2: O2, v3: O3, v4: O4, resultSelector: (v1: ObservedValueOf<O1>, v2: ObservedValueOf<O2>, v3: ObservedValueOf<O3>, v4: ObservedValueOf<O4>) => R, scheduler?: SchedulerLike): Observable<R>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>, R>(v1: O1, v2: O2, v3: O3, v4: O4, v5: O5, resultSelector: (v1: ObservedValueOf<O1>, v2: ObservedValueOf<O2>, v3: ObservedValueOf<O3>, v4: ObservedValueOf<O4>, v5: ObservedValueOf<O5>) => R, scheduler?: SchedulerLike): Observable<R>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>, O6 extends ObservableInput<any>, R>(v1: O1, v2: O2, v3: O3, v4: O4, v5: O5, v6: O6, resultSelector: (v1: ObservedValueOf<O1>, v2: ObservedValueOf<O2>, v3: ObservedValueOf<O3>, v4: ObservedValueOf<O4>, v5: ObservedValueOf<O5>, v6: ObservedValueOf<O6>) => R, scheduler?: SchedulerLike): Observable<R>;
// With a scheduler (deprecated)
/** @deprecated Passing a scheduler here is deprecated, use {@link subscribeOn} and/or {@link observeOn} instead */
export function combineLatest<O1 extends ObservableInput<any>>(sources: [O1], scheduler: SchedulerLike): Observable<[ObservedValueOf<O1>]>;
/** @deprecated Passing a scheduler here is deprecated, use {@link subscribeOn} and/or {@link observeOn} instead */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>>(sources: [O1, O2], scheduler: SchedulerLike): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>]>;
/** @deprecated Passing a scheduler here is deprecated, use {@link subscribeOn} and/or {@link observeOn} instead */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>>(sources: [O1, O2, O3], scheduler: SchedulerLike): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>, ObservedValueOf<O3>]>;
/** @deprecated Passing a scheduler here is deprecated, use {@link subscribeOn} and/or {@link observeOn} instead */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>>(sources: [O1, O2, O3, O4], scheduler: SchedulerLike): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>, ObservedValueOf<O3>, ObservedValueOf<O4>]>;
/** @deprecated Passing a scheduler here is deprecated, use {@link subscribeOn} and/or {@link observeOn} instead */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>>(sources: [O1, O2, O3, O4, O5], scheduler: SchedulerLike): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>, ObservedValueOf<O3>, ObservedValueOf<O4>, ObservedValueOf<O5>]>;
/** @deprecated Passing a scheduler here is deprecated, use {@link subscribeOn} and/or {@link observeOn} instead */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>, O6 extends ObservableInput<any>>(sources: [O1, O2, O3, O4, O5, O6], scheduler: SchedulerLike): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>, ObservedValueOf<O3>, ObservedValueOf<O4>, ObservedValueOf<O5>, ObservedValueOf<O6>]>;
/** @deprecated Passing a scheduler here is deprecated, use {@link subscribeOn} and/or {@link observeOn} instead */
export function combineLatest<O extends ObservableInput<any>>(sources: O[], scheduler: SchedulerLike): Observable<ObservedValueOf<O>[]>;
// Best case
export function combineLatest<O1 extends ObservableInput<any>>(sources: [O1]): Observable<[ObservedValueOf<O1>]>;
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>>(sources: [O1, O2]): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>]>;
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>>(sources: [O1, O2, O3]): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>, ObservedValueOf<O3>]>;
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>>(sources: [O1, O2, O3, O4]): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>, ObservedValueOf<O3>, ObservedValueOf<O4>]>;
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>>(sources: [O1, O2, O3, O4, O5]): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>, ObservedValueOf<O3>, ObservedValueOf<O4>, ObservedValueOf<O5>]>;
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>, O6 extends ObservableInput<any>>(sources: [O1, O2, O3, O4, O5, O6]): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>, ObservedValueOf<O3>, ObservedValueOf<O4>, ObservedValueOf<O5>, ObservedValueOf<O6>]>;
export function combineLatest<O extends ObservableInput<any>>(sources: O[]): Observable<ObservedValueOf<O>[]>;
// Standard calls
/** @deprecated Pass arguments in a single array instead `combineLatest([a, b, c])` */
export function combineLatest<O1 extends ObservableInput<any>>(v1: O1, scheduler?: SchedulerLike): Observable<[ObservedValueOf<O1>]>;
/** @deprecated Pass arguments in a single array instead `combineLatest([a, b, c])` */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>>(v1: O1, v2: O2, scheduler?: SchedulerLike): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>]>;
/** @deprecated Pass arguments in a single array instead `combineLatest([a, b, c])` */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>>(v1: O1, v2: O2, v3: O3, scheduler?: SchedulerLike): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>, ObservedValueOf<O3>]>;
/** @deprecated Pass arguments in a single array instead `combineLatest([a, b, c])` */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>>(v1: O1, v2: O2, v3: O3, v4: O4, scheduler?: SchedulerLike): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>, ObservedValueOf<O3>, ObservedValueOf<O4>]>;
/** @deprecated Pass arguments in a single array instead `combineLatest([a, b, c])` */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>>(v1: O1, v2: O2, v3: O3, v4: O4, v5: O5, scheduler?: SchedulerLike): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>, ObservedValueOf<O3>, ObservedValueOf<O4>, ObservedValueOf<O5>]>;
/** @deprecated Pass arguments in a single array instead `combineLatest([a, b, c])` */
export function combineLatest<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>, O6 extends ObservableInput<any>>(v1: O1, v2: O2, v3: O3, v4: O4, v5: O5, v6: O6, scheduler?: SchedulerLike): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>, ObservedValueOf<O3>, ObservedValueOf<O4>, ObservedValueOf<O5>, ObservedValueOf<O6>]>;
/** @deprecated Pass arguments in a single array instead `combineLatest([a, b, c])` */
export function combineLatest<O extends ObservableInput<any>>(...observables: O[]): Observable<any[]>;
/** @deprecated Pass arguments in a single array instead `combineLatest([a, b, c])` */
export function combineLatest<O extends ObservableInput<any>, R>(...observables: Array<ObservableInput<any> | ((...values: Array<any>) => R)>): Observable<R>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function combineLatest<O extends ObservableInput<any>, R>(array: O[], resultSelector: (...values: ObservedValueOf<O>[]) => R, scheduler?: SchedulerLike): Observable<R>;
/** @deprecated Passing a scheduler here is deprecated, use {@link subscribeOn} and/or {@link observeOn} instead */
export function combineLatest<O extends ObservableInput<any>>(...observables: Array<O | SchedulerLike>): Observable<any[]>;
/** @deprecated Passing a scheduler here is deprecated, use {@link subscribeOn} and/or {@link observeOn} instead */
export function combineLatest<O extends ObservableInput<any>, R>(...observables: Array<O | ((...values: ObservedValueOf<O>[]) => R) | SchedulerLike>): Observable<R>;
/** @deprecated Passing a scheduler here is deprecated, use {@link subscribeOn} and/or {@link observeOn} instead */
export function combineLatest<R>(...observables: Array<ObservableInput<any> | ((...values: Array<any>) => R) | SchedulerLike>): Observable<R>;
/* tslint:enable:max-line-length */
/**
* Combines multiple Observables to create an Observable whose values are
* calculated from the latest values of each of its input Observables.
*
* <span class="informal">Whenever any input Observable emits a value, it
* computes a formula using the latest values from all the inputs, then emits
* the output of that formula.</span>
*
* ![](combineLatest.png)
*
* `combineLatest` combines the values from all the Observables passed as
* arguments. This is done by subscribing to each Observable in order and,
* whenever any Observable emits, collecting an array of the most recent
* values from each Observable. So if you pass `n` Observables to operator,
* returned Observable will always emit an array of `n` values, in order
* corresponding to order of passed Observables (value from the first Observable
* on the first place and so on).
*
* Static version of `combineLatest` accepts either an array of Observables
* or each Observable can be put directly as an argument. Note that array of
* Observables is good choice, if you don't know beforehand how many Observables
* you will combine. Passing empty array will result in Observable that
* completes immediately.
*
* To ensure output array has always the same length, `combineLatest` will
* actually wait for all input Observables to emit at least once,
* before it starts emitting results. This means if some Observable emits
* values before other Observables started emitting, all these values but the last
* will be lost. On the other hand, if some Observable does not emit a value but
* completes, resulting Observable will complete at the same moment without
* emitting anything, since it will be now impossible to include value from
* completed Observable in resulting array. Also, if some input Observable does
* not emit any value and never completes, `combineLatest` will also never emit
* and never complete, since, again, it will wait for all streams to emit some
* value.
*
* If at least one Observable was passed to `combineLatest` and all passed Observables
* emitted something, resulting Observable will complete when all combined
* streams complete. So even if some Observable completes, result of
* `combineLatest` will still emit values when other Observables do. In case
* of completed Observable, its value from now on will always be the last
* emitted value. On the other hand, if any Observable errors, `combineLatest`
* will error immediately as well, and all other Observables will be unsubscribed.
*
* `combineLatest` accepts as optional parameter `project` function, which takes
* as arguments all values that would normally be emitted by resulting Observable.
* `project` can return any kind of value, which will be then emitted by Observable
* instead of default array. Note that `project` does not take as argument that array
* of values, but values themselves. That means default `project` can be imagined
* as function that takes all its arguments and puts them into an array.
*
* ## Examples
* ### Combine two timer Observables
* ```ts
* import { combineLatest, timer } from 'rxjs';
*
* const firstTimer = timer(0, 1000); // emit 0, 1, 2... after every second, starting from now
* const secondTimer = timer(500, 1000); // emit 0, 1, 2... after every second, starting 0,5s from now
* const combinedTimers = combineLatest(firstTimer, secondTimer);
* combinedTimers.subscribe(value => console.log(value));
* // Logs
* // [0, 0] after 0.5s
* // [1, 0] after 1s
* // [1, 1] after 1.5s
* // [2, 1] after 2s
* ```
*
* ### Combine an array of Observables
* ```ts
* import { combineLatest, of } from 'rxjs';
* import { delay, starWith } from 'rxjs/operators';
*
* const observables = [1, 5, 10].map(
* n => of(n).pipe(
* delay(n * 1000), // emit 0 and then emit n after n seconds
* startWith(0),
* )
* );
* const combined = combineLatest(observables);
* combined.subscribe(value => console.log(value));
* // Logs
* // [0, 0, 0] immediately
* // [1, 0, 0] after 1s
* // [1, 5, 0] after 5s
* // [1, 5, 10] after 10s
* ```
*
*
* ### Use project function to dynamically calculate the Body-Mass Index
* ```ts
* import { combineLatest, of } from 'rxjs';
* import { map } from 'rxjs/operators';
*
* const weight = of(70, 72, 76, 79, 75);
* const height = of(1.76, 1.77, 1.78);
* const bmi = combineLatest(weight, height).pipe(
* map(([w, h]) => w / (h * h)),
* );
* bmi.subscribe(x => console.log('BMI is ' + x));
*
* // With output to console:
* // BMI is 24.212293388429753
* // BMI is 23.93948099205209
* // BMI is 23.671253629592222
* ```
*
* @see {@link combineAll}
* @see {@link merge}
* @see {@link withLatestFrom}
*
* @param {ObservableInput} observable1 An input Observable to combine with other Observables.
* @param {ObservableInput} observable2 An input Observable to combine with other Observables.
* More than one input Observables may be given as arguments
* or an array of Observables may be given as the first argument.
* @param {function} [project] An optional function to project the values from
* the combined latest values into a new value on the output Observable.
* @param {SchedulerLike} [scheduler=null] The {@link SchedulerLike} to use for subscribing to
* each input Observable.
* @return {Observable} An Observable of projected values from the most recent
* values from each input Observable, or an array of the most recent values from
* each input Observable.
*/
export function combineLatest<O extends ObservableInput<any>, R>(
...observables: (O | ((...values: ObservedValueOf<O>[]) => R) | SchedulerLike)[]
): Observable<R> {
let resultSelector: (...values: Array<any>) => R = null;
let scheduler: SchedulerLike = null;
if (isScheduler(observables[observables.length - 1])) {
scheduler = observables.pop() as SchedulerLike;
}
if (typeof observables[observables.length - 1] === 'function') {
resultSelector = observables.pop() as (...values: Array<any>) => R;
}
// if the first and only other argument besides the resultSelector is an array
// assume it's been called with `combineLatest([obs1, obs2, obs3], resultSelector)`
if (observables.length === 1 && isArray(observables[0])) {
observables = observables[0] as any;
}
return fromArray(observables, scheduler).lift(new CombineLatestOperator<ObservedValueOf<O>, R>(resultSelector));
}
export class CombineLatestOperator<T, R> implements Operator<T, R> {
constructor(private resultSelector?: (...values: Array<any>) => R) {
}
call(subscriber: Subscriber<R>, source: any): any {
return source.subscribe(new CombineLatestSubscriber(subscriber, this.resultSelector));
}
}
/**
* We need this JSDoc comment for affecting ESDoc.
* @ignore
* @extends {Ignored}
*/
export class CombineLatestSubscriber<T, R> extends OuterSubscriber<T, R> {
private active: number = 0;
private values: any[] = [];
private observables: any[] = [];
private toRespond: number;
constructor(destination: Subscriber<R>, private resultSelector?: (...values: Array<any>) => R) {
super(destination);
}
protected _next(observable: any) {
this.values.push(NONE);
this.observables.push(observable);
}
protected _complete() {
const observables = this.observables;
const len = observables.length;
if (len === 0) {
this.destination.complete();
} else {
this.active = len;
this.toRespond = len;
for (let i = 0; i < len; i++) {
const observable = observables[i];
this.add(subscribeToResult(this, observable, observable, i));
}
}
}
notifyComplete(unused: Subscriber<R>): void {
if ((this.active -= 1) === 0) {
this.destination.complete();
}
}
notifyNext(outerValue: T, innerValue: R,
outerIndex: number, innerIndex: number,
innerSub: InnerSubscriber<T, R>): void {
const values = this.values;
const oldVal = values[outerIndex];
const toRespond = !this.toRespond
? 0
: oldVal === NONE ? --this.toRespond : this.toRespond;
values[outerIndex] = innerValue;
if (toRespond === 0) {
if (this.resultSelector) {
this._tryResultSelector(values);
} else {
this.destination.next(values.slice());
}
}
}
private _tryResultSelector(values: any[]) {
let result: any;
try {
result = this.resultSelector.apply(this, values);
} catch (err) {
this.destination.error(err);
return;
}
this.destination.next(result);
}
}

147
node_modules/rxjs/src/internal/observable/concat.ts generated vendored Normal file
View File

@ -0,0 +1,147 @@
import { Observable } from '../Observable';
import { ObservableInput, SchedulerLike, ObservedValueOf } from '../types';
import { isScheduler } from '../util/isScheduler';
import { of } from './of';
import { from } from './from';
import { concatAll } from '../operators/concatAll';
/* tslint:disable:max-line-length */
/** @deprecated Use {@link scheduled} and {@link concatAll} (e.g. `scheduled([o1, o2, o3], scheduler).pipe(concatAll())`) */
export function concat<O1 extends ObservableInput<any>>(v1: O1, scheduler: SchedulerLike): Observable<ObservedValueOf<O1>>;
/** @deprecated Use {@link scheduled} and {@link concatAll} (e.g. `scheduled([o1, o2, o3], scheduler).pipe(concatAll())`) */
export function concat<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>>(v1: O1, v2: O2, scheduler: SchedulerLike): Observable<ObservedValueOf<O1> | ObservedValueOf<O2>>;
/** @deprecated Use {@link scheduled} and {@link concatAll} (e.g. `scheduled([o1, o2, o3], scheduler).pipe(concatAll())`) */
export function concat<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>>(v1: O1, v2: O2, v3: O3, scheduler: SchedulerLike): Observable<ObservedValueOf<O1> | ObservedValueOf<O2> | ObservedValueOf<O3>>;
/** @deprecated Use {@link scheduled} and {@link concatAll} (e.g. `scheduled([o1, o2, o3], scheduler).pipe(concatAll())`) */
export function concat<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>>(v1: O1, v2: O2, v3: O3, v4: O4, scheduler: SchedulerLike): Observable<ObservedValueOf<O1> | ObservedValueOf<O2> | ObservedValueOf<O3> | ObservedValueOf<O4>>;
/** @deprecated Use {@link scheduled} and {@link concatAll} (e.g. `scheduled([o1, o2, o3], scheduler).pipe(concatAll())`) */
export function concat<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>>(v1: O1, v2: O2, v3: O3, v4: O4, v5: O5, scheduler: SchedulerLike): Observable<ObservedValueOf<O1> | ObservedValueOf<O2> | ObservedValueOf<O3> | ObservedValueOf<O4> | ObservedValueOf<O5>>;
/** @deprecated Use {@link scheduled} and {@link concatAll} (e.g. `scheduled([o1, o2, o3], scheduler).pipe(concatAll())`) */
export function concat<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>, O6 extends ObservableInput<any>>(v1: O1, v2: O2, v3: O3, v4: O4, v5: O5, v6: O6, scheduler: SchedulerLike): Observable<ObservedValueOf<O1> | ObservedValueOf<O2> | ObservedValueOf<O3> | ObservedValueOf<O4> | ObservedValueOf<O5> | ObservedValueOf<O6>>;
export function concat<O1 extends ObservableInput<any>>(v1: O1): Observable<ObservedValueOf<O1>>;
export function concat<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>>(v1: O1, v2: O2): Observable<ObservedValueOf<O1> | ObservedValueOf<O2>>;
export function concat<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>>(v1: O1, v2: O2, v3: O3): Observable<ObservedValueOf<O1> | ObservedValueOf<O2> | ObservedValueOf<O3>>;
export function concat<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>>(v1: O1, v2: O2, v3: O3, v4: O4): Observable<ObservedValueOf<O1> | ObservedValueOf<O2> | ObservedValueOf<O3> | ObservedValueOf<O4>>;
export function concat<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>>(v1: O1, v2: O2, v3: O3, v4: O4, v5: O5): Observable<ObservedValueOf<O1> | ObservedValueOf<O2> | ObservedValueOf<O3> | ObservedValueOf<O4> | ObservedValueOf<O5>>;
export function concat<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>, O6 extends ObservableInput<any>>(v1: O1, v2: O2, v3: O3, v4: O4, v5: O5, v6: O6): Observable<ObservedValueOf<O1> | ObservedValueOf<O2> | ObservedValueOf<O3> | ObservedValueOf<O4> | ObservedValueOf<O5> | ObservedValueOf<O6>>;
export function concat<O extends ObservableInput<any>>(...observables: O[]): Observable<ObservedValueOf<O>>;
/** @deprecated Use {@link scheduled} and {@link concatAll} (e.g. `scheduled([o1, o2, o3], scheduler).pipe(concatAll())`) */
export function concat<O extends ObservableInput<any>>(...observables: (O | SchedulerLike)[]): Observable<ObservedValueOf<O>>;
export function concat<R>(...observables: ObservableInput<any>[]): Observable<R>;
/** @deprecated Use {@link scheduled} and {@link concatAll} (e.g. `scheduled([o1, o2, o3], scheduler).pipe(concatAll())`) */
export function concat<R>(...observables: (ObservableInput<any> | SchedulerLike)[]): Observable<R>;
/* tslint:enable:max-line-length */
/**
* Creates an output Observable which sequentially emits all values from given
* Observable and then moves on to the next.
*
* <span class="informal">Concatenates multiple Observables together by
* sequentially emitting their values, one Observable after the other.</span>
*
* ![](concat.png)
*
* `concat` joins multiple Observables together, by subscribing to them one at a time and
* merging their results into the output Observable. You can pass either an array of
* Observables, or put them directly as arguments. Passing an empty array will result
* in Observable that completes immediately.
*
* `concat` will subscribe to first input Observable and emit all its values, without
* changing or affecting them in any way. When that Observable completes, it will
* subscribe to then next Observable passed and, again, emit its values. This will be
* repeated, until the operator runs out of Observables. When last input Observable completes,
* `concat` will complete as well. At any given moment only one Observable passed to operator
* emits values. If you would like to emit values from passed Observables concurrently, check out
* {@link merge} instead, especially with optional `concurrent` parameter. As a matter of fact,
* `concat` is an equivalent of `merge` operator with `concurrent` parameter set to `1`.
*
* Note that if some input Observable never completes, `concat` will also never complete
* and Observables following the one that did not complete will never be subscribed. On the other
* hand, if some Observable simply completes immediately after it is subscribed, it will be
* invisible for `concat`, which will just move on to the next Observable.
*
* If any Observable in chain errors, instead of passing control to the next Observable,
* `concat` will error immediately as well. Observables that would be subscribed after
* the one that emitted error, never will.
*
* If you pass to `concat` the same Observable many times, its stream of values
* will be "replayed" on every subscription, which means you can repeat given Observable
* as many times as you like. If passing the same Observable to `concat` 1000 times becomes tedious,
* you can always use {@link repeat}.
*
* ## Examples
* ### Concatenate a timer counting from 0 to 3 with a synchronous sequence from 1 to 10
* ```ts
* import { concat, interval, range } from 'rxjs';
* import { take } from 'rxjs/operators';
*
* const timer = interval(1000).pipe(take(4));
* const sequence = range(1, 10);
* const result = concat(timer, sequence);
* result.subscribe(x => console.log(x));
*
* // results in:
* // 0 -1000ms-> 1 -1000ms-> 2 -1000ms-> 3 -immediate-> 1 ... 10
* ```
*
* ### Concatenate 3 Observables
* ```ts
* import { concat, interval } from 'rxjs';
* import { take } from 'rxjs/operators';
*
* const timer1 = interval(1000).pipe(take(10));
* const timer2 = interval(2000).pipe(take(6));
* const timer3 = interval(500).pipe(take(10));
*
* const result = concat(timer1, timer2, timer3);
* result.subscribe(x => console.log(x));
*
* // results in the following:
* // (Prints to console sequentially)
* // -1000ms-> 0 -1000ms-> 1 -1000ms-> ... 9
* // -2000ms-> 0 -2000ms-> 1 -2000ms-> ... 5
* // -500ms-> 0 -500ms-> 1 -500ms-> ... 9
* ```
*
* ### Concatenate the same Observable to repeat it
* ```ts
* import { concat, interval } from 'rxjs';
* import { take } from 'rxjs/operators';
*
* const timer = interval(1000).pipe(take(2));
*
* concat(timer, timer) // concatenating the same Observable!
* .subscribe(
* value => console.log(value),
* err => {},
* () => console.log('...and it is done!')
* );
*
* // Logs:
* // 0 after 1s
* // 1 after 2s
* // 0 after 3s
* // 1 after 4s
* // "...and it is done!" also after 4s
* ```
*
* @see {@link concatAll}
* @see {@link concatMap}
* @see {@link concatMapTo}
* @see {@link startWith}
* @see {@link endWith}
*
* @param {ObservableInput} input1 An input Observable to concatenate with others.
* @param {ObservableInput} input2 An input Observable to concatenate with others.
* More than one input Observables may be given as argument.
* @param {SchedulerLike} [scheduler=null] An optional {@link SchedulerLike} to schedule each
* Observable subscription on.
* @return {Observable} All values of each passed Observable merged into a
* single Observable, in order, in serial fashion.
* @static true
* @name concat
* @owner Observable
*/
export function concat<O extends ObservableInput<any>, R>(...observables: Array<O | SchedulerLike>): Observable<ObservedValueOf<O> | R> {
return concatAll<R>()(of(...observables));
}

67
node_modules/rxjs/src/internal/observable/defer.ts generated vendored Normal file
View File

@ -0,0 +1,67 @@
import { Observable } from '../Observable';
import { SubscribableOrPromise, ObservedValueOf, ObservableInput } from '../types';
import { from } from './from'; // lol
import { empty } from './empty';
/**
* Creates an Observable that, on subscribe, calls an Observable factory to
* make an Observable for each new Observer.
*
* <span class="informal">Creates the Observable lazily, that is, only when it
* is subscribed.
* </span>
*
* ![](defer.png)
*
* `defer` allows you to create the Observable only when the Observer
* subscribes, and create a fresh Observable for each Observer. It waits until
* an Observer subscribes to it, and then it generates an Observable,
* typically with an Observable factory function. It does this afresh for each
* subscriber, so although each subscriber may think it is subscribing to the
* same Observable, in fact each subscriber gets its own individual
* Observable.
*
* ## Example
* ### Subscribe to either an Observable of clicks or an Observable of interval, at random
* ```ts
* import { defer, fromEvent, interval } from 'rxjs';
*
* const clicksOrInterval = defer(function () {
* return Math.random() > 0.5
* ? fromEvent(document, 'click')
* : interval(1000);
* });
* clicksOrInterval.subscribe(x => console.log(x));
*
* // Results in the following behavior:
* // If the result of Math.random() is greater than 0.5 it will listen
* // for clicks anywhere on the "document"; when document is clicked it
* // will log a MouseEvent object to the console. If the result is less
* // than 0.5 it will emit ascending numbers, one every second(1000ms).
* ```
*
* @see {@link Observable}
*
* @param {function(): SubscribableOrPromise} observableFactory The Observable
* factory function to invoke for each Observer that subscribes to the output
* Observable. May also return a Promise, which will be converted on the fly
* to an Observable.
* @return {Observable} An Observable whose Observers' subscriptions trigger
* an invocation of the given Observable factory function.
* @static true
* @name defer
* @owner Observable
*/
export function defer<R extends ObservableInput<any> | void>(observableFactory: () => R): Observable<ObservedValueOf<R>> {
return new Observable<ObservedValueOf<R>>(subscriber => {
let input: R | void;
try {
input = observableFactory();
} catch (err) {
subscriber.error(err);
return undefined;
}
const source = input ? from(input as ObservableInput<ObservedValueOf<R>>) : empty();
return source.subscribe(subscriber);
});
}

View File

@ -0,0 +1,550 @@
import { root } from '../../util/root';
import { Observable } from '../../Observable';
import { Subscriber } from '../../Subscriber';
import { TeardownLogic } from '../../types';
import { map } from '../../operators/map';
export interface AjaxRequest {
url?: string;
body?: any;
user?: string;
async?: boolean;
method?: string;
headers?: Object;
timeout?: number;
password?: string;
hasContent?: boolean;
crossDomain?: boolean;
withCredentials?: boolean;
createXHR?: () => XMLHttpRequest;
progressSubscriber?: Subscriber<any>;
responseType?: string;
}
function getCORSRequest(): XMLHttpRequest {
if (root.XMLHttpRequest) {
return new root.XMLHttpRequest();
} else if (!!root.XDomainRequest) {
return new root.XDomainRequest();
} else {
throw new Error('CORS is not supported by your browser');
}
}
function getXMLHttpRequest(): XMLHttpRequest {
if (root.XMLHttpRequest) {
return new root.XMLHttpRequest();
} else {
let progId: string;
try {
const progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
for (let i = 0; i < 3; i++) {
try {
progId = progIds[i];
if (new root.ActiveXObject(progId)) {
break;
}
} catch (e) {
//suppress exceptions
}
}
return new root.ActiveXObject(progId);
} catch (e) {
throw new Error('XMLHttpRequest is not supported by your browser');
}
}
}
export interface AjaxCreationMethod {
(urlOrRequest: string | AjaxRequest): Observable<AjaxResponse>;
get(url: string, headers?: Object): Observable<AjaxResponse>;
post(url: string, body?: any, headers?: Object): Observable<AjaxResponse>;
put(url: string, body?: any, headers?: Object): Observable<AjaxResponse>;
patch(url: string, body?: any, headers?: Object): Observable<AjaxResponse>;
delete(url: string, headers?: Object): Observable<AjaxResponse>;
getJSON<T>(url: string, headers?: Object): Observable<T>;
}
export function ajaxGet(url: string, headers: Object = null) {
return new AjaxObservable<AjaxResponse>({ method: 'GET', url, headers });
}
export function ajaxPost(url: string, body?: any, headers?: Object): Observable<AjaxResponse> {
return new AjaxObservable<AjaxResponse>({ method: 'POST', url, body, headers });
}
export function ajaxDelete(url: string, headers?: Object): Observable<AjaxResponse> {
return new AjaxObservable<AjaxResponse>({ method: 'DELETE', url, headers });
}
export function ajaxPut(url: string, body?: any, headers?: Object): Observable<AjaxResponse> {
return new AjaxObservable<AjaxResponse>({ method: 'PUT', url, body, headers });
}
export function ajaxPatch(url: string, body?: any, headers?: Object): Observable<AjaxResponse> {
return new AjaxObservable<AjaxResponse>({ method: 'PATCH', url, body, headers });
}
const mapResponse = map((x: AjaxResponse, index: number) => x.response);
export function ajaxGetJSON<T>(url: string, headers?: Object): Observable<T> {
return mapResponse(
new AjaxObservable<AjaxResponse>({
method: 'GET',
url,
responseType: 'json',
headers
})
);
}
/**
* We need this JSDoc comment for affecting ESDoc.
* @extends {Ignored}
* @hide true
*/
export class AjaxObservable<T> extends Observable<T> {
/**
* Creates an observable for an Ajax request with either a request object with
* url, headers, etc or a string for a URL.
*
* ## Example
* ```ts
* import { ajax } from 'rxjs/ajax';
*
* const source1 = ajax('/products');
* const source2 = ajax({ url: 'products', method: 'GET' });
* ```
*
* @param {string|Object} request Can be one of the following:
* A string of the URL to make the Ajax call.
* An object with the following properties
* - url: URL of the request
* - body: The body of the request
* - method: Method of the request, such as GET, POST, PUT, PATCH, DELETE
* - async: Whether the request is async
* - headers: Optional headers
* - crossDomain: true if a cross domain request, else false
* - createXHR: a function to override if you need to use an alternate
* XMLHttpRequest implementation.
* - resultSelector: a function to use to alter the output value type of
* the Observable. Gets {@link AjaxResponse} as an argument.
* @return {Observable} An observable sequence containing the XMLHttpRequest.
* @static true
* @name ajax
* @owner Observable
* @nocollapse
*/
static create: AjaxCreationMethod = (() => {
const create: any = (urlOrRequest: string | AjaxRequest) => {
return new AjaxObservable(urlOrRequest);
};
create.get = ajaxGet;
create.post = ajaxPost;
create.delete = ajaxDelete;
create.put = ajaxPut;
create.patch = ajaxPatch;
create.getJSON = ajaxGetJSON;
return <AjaxCreationMethod>create;
})();
private request: AjaxRequest;
constructor(urlOrRequest: string | AjaxRequest) {
super();
const request: AjaxRequest = {
async: true,
createXHR: function(this: AjaxRequest) {
return this.crossDomain ? getCORSRequest() : getXMLHttpRequest();
},
crossDomain: true,
withCredentials: false,
headers: {},
method: 'GET',
responseType: 'json',
timeout: 0
};
if (typeof urlOrRequest === 'string') {
request.url = urlOrRequest;
} else {
for (const prop in urlOrRequest) {
if (urlOrRequest.hasOwnProperty(prop)) {
request[prop] = urlOrRequest[prop];
}
}
}
this.request = request;
}
/** @deprecated This is an internal implementation detail, do not use. */
_subscribe(subscriber: Subscriber<T>): TeardownLogic {
return new AjaxSubscriber(subscriber, this.request);
}
}
/**
* We need this JSDoc comment for affecting ESDoc.
* @ignore
* @extends {Ignored}
*/
export class AjaxSubscriber<T> extends Subscriber<Event> {
private xhr: XMLHttpRequest;
private done: boolean = false;
constructor(destination: Subscriber<T>, public request: AjaxRequest) {
super(destination);
const headers = request.headers = request.headers || {};
// force CORS if requested
if (!request.crossDomain && !this.getHeader(headers, 'X-Requested-With')) {
headers['X-Requested-With'] = 'XMLHttpRequest';
}
// ensure content type is set
let contentTypeHeader = this.getHeader(headers, 'Content-Type');
if (!contentTypeHeader && !(root.FormData && request.body instanceof root.FormData) && typeof request.body !== 'undefined') {
headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
}
// properly serialize body
request.body = this.serializeBody(request.body, this.getHeader(request.headers, 'Content-Type'));
this.send();
}
next(e: Event): void {
this.done = true;
const { xhr, request, destination } = this;
let result;
try {
result = new AjaxResponse(e, xhr, request);
} catch (err) {
return destination.error(err);
}
destination.next(result);
}
private send(): void {
const {
request,
request: { user, method, url, async, password, headers, body }
} = this;
try {
const xhr = this.xhr = request.createXHR();
// set up the events before open XHR
// https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
// You need to add the event listeners before calling open() on the request.
// Otherwise the progress events will not fire.
this.setupEvents(xhr, request);
// open XHR
if (user) {
xhr.open(method, url, async, user, password);
} else {
xhr.open(method, url, async);
}
// timeout, responseType and withCredentials can be set once the XHR is open
if (async) {
xhr.timeout = request.timeout;
xhr.responseType = request.responseType as any;
}
if ('withCredentials' in xhr) {
xhr.withCredentials = !!request.withCredentials;
}
// set headers
this.setHeaders(xhr, headers);
// finally send the request
if (body) {
xhr.send(body);
} else {
xhr.send();
}
} catch (err) {
this.error(err);
}
}
private serializeBody(body: any, contentType?: string) {
if (!body || typeof body === 'string') {
return body;
} else if (root.FormData && body instanceof root.FormData) {
return body;
}
if (contentType) {
const splitIndex = contentType.indexOf(';');
if (splitIndex !== -1) {
contentType = contentType.substring(0, splitIndex);
}
}
switch (contentType) {
case 'application/x-www-form-urlencoded':
return Object.keys(body).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(body[key])}`).join('&');
case 'application/json':
return JSON.stringify(body);
default:
return body;
}
}
private setHeaders(xhr: XMLHttpRequest, headers: Object) {
for (let key in headers) {
if (headers.hasOwnProperty(key)) {
xhr.setRequestHeader(key, headers[key]);
}
}
}
private getHeader(headers: {}, headerName: string): any {
for (let key in headers) {
if (key.toLowerCase() === headerName.toLowerCase()) {
return headers[key];
}
}
return undefined;
}
private setupEvents(xhr: XMLHttpRequest, request: AjaxRequest) {
const progressSubscriber = request.progressSubscriber;
function xhrTimeout(this: XMLHttpRequest, e: ProgressEvent): void {
const {subscriber, progressSubscriber, request } = (<any>xhrTimeout);
if (progressSubscriber) {
progressSubscriber.error(e);
}
let error;
try {
error = new AjaxTimeoutError(this, request); // TODO: Make betterer.
} catch (err) {
error = err;
}
subscriber.error(error);
}
xhr.ontimeout = xhrTimeout;
(<any>xhrTimeout).request = request;
(<any>xhrTimeout).subscriber = this;
(<any>xhrTimeout).progressSubscriber = progressSubscriber;
if (xhr.upload && 'withCredentials' in xhr) {
if (progressSubscriber) {
let xhrProgress: (e: ProgressEvent) => void;
xhrProgress = function(e: ProgressEvent) {
const { progressSubscriber } = (<any>xhrProgress);
progressSubscriber.next(e);
};
if (root.XDomainRequest) {
xhr.onprogress = xhrProgress;
} else {
xhr.upload.onprogress = xhrProgress;
}
(<any>xhrProgress).progressSubscriber = progressSubscriber;
}
let xhrError: (e: any) => void;
xhrError = function(this: XMLHttpRequest, e: ErrorEvent) {
const { progressSubscriber, subscriber, request } = (<any>xhrError);
if (progressSubscriber) {
progressSubscriber.error(e);
}
let error;
try {
error = new AjaxError('ajax error', this, request);
} catch (err) {
error = err;
}
subscriber.error(error);
};
xhr.onerror = xhrError;
(<any>xhrError).request = request;
(<any>xhrError).subscriber = this;
(<any>xhrError).progressSubscriber = progressSubscriber;
}
function xhrReadyStateChange(this: XMLHttpRequest, e: Event) {
return;
}
xhr.onreadystatechange = xhrReadyStateChange;
(<any>xhrReadyStateChange).subscriber = this;
(<any>xhrReadyStateChange).progressSubscriber = progressSubscriber;
(<any>xhrReadyStateChange).request = request;
function xhrLoad(this: XMLHttpRequest, e: Event) {
const { subscriber, progressSubscriber, request } = (<any>xhrLoad);
if (this.readyState === 4) {
// normalize IE9 bug (http://bugs.jquery.com/ticket/1450)
let status: number = this.status === 1223 ? 204 : this.status;
let response: any = (this.responseType === 'text' ? (
this.response || this.responseText) : this.response);
// fix status code when it is 0 (0 status is undocumented).
// Occurs when accessing file resources or on Android 4.1 stock browser
// while retrieving files from application cache.
if (status === 0) {
status = response ? 200 : 0;
}
// 4xx and 5xx should error (https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)
if (status < 400) {
if (progressSubscriber) {
progressSubscriber.complete();
}
subscriber.next(e);
subscriber.complete();
} else {
if (progressSubscriber) {
progressSubscriber.error(e);
}
let error;
try {
error = new AjaxError('ajax error ' + status, this, request);
} catch (err) {
error = err;
}
subscriber.error(error);
}
}
}
xhr.onload = xhrLoad;
(<any>xhrLoad).subscriber = this;
(<any>xhrLoad).progressSubscriber = progressSubscriber;
(<any>xhrLoad).request = request;
}
unsubscribe() {
const { done, xhr } = this;
if (!done && xhr && xhr.readyState !== 4 && typeof xhr.abort === 'function') {
xhr.abort();
}
super.unsubscribe();
}
}
/**
* A normalized AJAX response.
*
* @see {@link ajax}
*
* @class AjaxResponse
*/
export class AjaxResponse {
/** @type {number} The HTTP status code */
status: number;
/** @type {string|ArrayBuffer|Document|object|any} The response data */
response: any;
/** @type {string} The raw responseText */
responseText: string;
/** @type {string} The responseType (e.g. 'json', 'arraybuffer', or 'xml') */
responseType: string;
constructor(public originalEvent: Event, public xhr: XMLHttpRequest, public request: AjaxRequest) {
this.status = xhr.status;
this.responseType = xhr.responseType || request.responseType;
this.response = parseXhrResponse(this.responseType, xhr);
}
}
export type AjaxErrorNames = 'AjaxError' | 'AjaxTimeoutError';
/**
* A normalized AJAX error.
*
* @see {@link ajax}
*
* @class AjaxError
*/
export interface AjaxError extends Error {
/** @type {XMLHttpRequest} The XHR instance associated with the error */
xhr: XMLHttpRequest;
/** @type {AjaxRequest} The AjaxRequest associated with the error */
request: AjaxRequest;
/** @type {number} The HTTP status code */
status: number;
/** @type {string} The responseType (e.g. 'json', 'arraybuffer', or 'xml') */
responseType: string;
/** @type {string|ArrayBuffer|Document|object|any} The response data */
response: any;
}
export interface AjaxErrorCtor {
new(message: string, xhr: XMLHttpRequest, request: AjaxRequest): AjaxError;
}
const AjaxErrorImpl = (() => {
function AjaxErrorImpl(this: any, message: string, xhr: XMLHttpRequest, request: AjaxRequest): AjaxError {
Error.call(this);
this.message = message;
this.name = 'AjaxError';
this.xhr = xhr;
this.request = request;
this.status = xhr.status;
this.responseType = xhr.responseType || request.responseType;
this.response = parseXhrResponse(this.responseType, xhr);
return this;
}
AjaxErrorImpl.prototype = Object.create(Error.prototype);
return AjaxErrorImpl;
})();
export const AjaxError: AjaxErrorCtor = AjaxErrorImpl as any;
function parseJson(xhr: XMLHttpRequest) {
// HACK(benlesh): TypeScript shennanigans
// tslint:disable-next-line:no-any XMLHttpRequest is defined to always have 'response' inferring xhr as never for the else clause.
if ('response' in (xhr as any)) {
//IE does not support json as responseType, parse it internally
return xhr.responseType ? xhr.response : JSON.parse(xhr.response || xhr.responseText || 'null');
} else {
return JSON.parse((xhr as any).responseText || 'null');
}
}
function parseXhrResponse(responseType: string, xhr: XMLHttpRequest) {
switch (responseType) {
case 'json':
return parseJson(xhr);
case 'xml':
return xhr.responseXML;
case 'text':
default:
// HACK(benlesh): TypeScript shennanigans
// tslint:disable-next-line:no-any XMLHttpRequest is defined to always have 'response' inferring xhr as never for the else sub-expression.
return ('response' in (xhr as any)) ? xhr.response : xhr.responseText;
}
}
export interface AjaxTimeoutError extends AjaxError {
}
export interface AjaxTimeoutErrorCtor {
new(xhr: XMLHttpRequest, request: AjaxRequest): AjaxTimeoutError;
}
function AjaxTimeoutErrorImpl(this: any, xhr: XMLHttpRequest, request: AjaxRequest) {
AjaxError.call(this, 'ajax timeout', xhr, request);
this.name = 'AjaxTimeoutError';
return this;
}
/**
* @see {@link ajax}
*
* @class AjaxTimeoutError
*/
export const AjaxTimeoutError: AjaxTimeoutErrorCtor = AjaxTimeoutErrorImpl as any;

View File

@ -0,0 +1,77 @@
import { Subscriber } from '../../Subscriber';
import { AjaxResponse } from './AjaxObservable';
/**
* @see {@link ajax}
*
* @interface
* @name AjaxRequest
* @noimport true
*/
export class AjaxRequestDoc {
/**
* @type {string}
*/
url: string = '';
/**
* @type {number}
*/
body: any = 0;
/**
* @type {string}
*/
user: string = '';
/**
* @type {boolean}
*/
async: boolean = false;
/**
* @type {string}
*/
method: string = '';
/**
* @type {Object}
*/
headers: Object = null;
/**
* @type {number}
*/
timeout: number = 0;
/**
* @type {string}
*/
password: string = '';
/**
* @type {boolean}
*/
hasContent: boolean = false;
/**
* @type {boolean}
*/
crossDomain: boolean = false;
/**
* @type {boolean}
*/
withCredentials: boolean = false;
/**
* @return {XMLHttpRequest}
*/
createXHR(): XMLHttpRequest {
return null;
}
/**
* @type {Subscriber}
*/
progressSubscriber: Subscriber<any> = null;
/**
* @param {AjaxResponse} response
* @return {T}
*/
resultSelector<T>(response: AjaxResponse): T {
return null;
}
/**
* @type {string}
*/
responseType: string = '';
}

View File

@ -0,0 +1,387 @@
import { Subject, AnonymousSubject } from '../../Subject';
import { Subscriber } from '../../Subscriber';
import { Observable } from '../../Observable';
import { Subscription } from '../../Subscription';
import { Operator } from '../../Operator';
import { ReplaySubject } from '../../ReplaySubject';
import { Observer, NextObserver } from '../../types';
/**
* WebSocketSubjectConfig is a plain Object that allows us to make our
* webSocket configurable.
*
* <span class="informal">Provides flexibility to {@link webSocket}</span>
*
* It defines a set of properties to provide custom behavior in specific
* moments of the socket's lifecycle. When the connection opens we can
* use `openObserver`, when the connection is closed `closeObserver`, if we
* are interested in listening for data comming from server: `deserializer`,
* which allows us to customize the deserialization strategy of data before passing it
* to the socket client. By default `deserializer` is going to apply `JSON.parse` to each message comming
* from the Server.
*
* ## Example
* **deserializer**, the default for this property is `JSON.parse` but since there are just two options
* for incomming data, either be text or binarydata. We can apply a custom deserialization strategy
* or just simply skip the default behaviour.
* ```ts
* import { webSocket } from 'rxjs/webSocket';
*
* const wsSubject = webSocket({
* url: 'ws://localhost:8081',
* //Apply any transformation of your choice.
* deserializer: ({data}) => data
* });
*
* wsSubject.subscribe(console.log);
*
* // Let's suppose we have this on the Server: ws.send("This is a msg from the server")
* //output
* //
* // This is a msg from the server
* ```
*
* **serializer** allows us tom apply custom serialization strategy but for the outgoing messages
* ```ts
* import { webSocket } from 'rxjs/webSocket';
*
* const wsSubject = webSocket({
* url: 'ws://localhost:8081',
* //Apply any transformation of your choice.
* serializer: msg => JSON.stringify({channel: "webDevelopment", msg: msg})
* });
*
* wsSubject.subscribe(() => subject.next("msg to the server"));
*
* // Let's suppose we have this on the Server: ws.send("This is a msg from the server")
* //output
* //
* // {"channel":"webDevelopment","msg":"msg to the server"}
* ```
*
* **closeObserver** allows us to set a custom error when an error raise up.
* ```ts
* import { webSocket } from 'rxjs/webSocket';
*
* const wsSubject = webSocket({
* url: 'ws://localhost:8081',
* closeObserver: {
next(closeEvent) {
const customError = { code: 6666, reason: "Custom evil reason" }
console.log(`code: ${customError.code}, reason: ${customError.reason}`);
}
}
* });
*
* //output
* // code: 6666, reason: Custom evil reason
* ```
*
* **openObserver**, Let's say we need to make some kind of init task before sending/receiving msgs to the
* webSocket or sending notification that the connection was successful, this is when
* openObserver is usefull for.
* ```ts
* import { webSocket } from 'rxjs/webSocket';
*
* const wsSubject = webSocket({
* url: 'ws://localhost:8081',
* openObserver: {
* next: () => {
* console.log('connetion ok');
* }
* },
* });
*
* //output
* // connetion ok`
* ```
* */
export interface WebSocketSubjectConfig<T> {
/** The url of the socket server to connect to */
url: string;
/** The protocol to use to connect */
protocol?: string | Array<string>;
/** @deprecated use {@link deserializer} */
resultSelector?: (e: MessageEvent) => T;
/**
* A serializer used to create messages from passed values before the
* messages are sent to the server. Defaults to JSON.stringify.
*/
serializer?: (value: T) => WebSocketMessage;
/**
* A deserializer used for messages arriving on the socket from the
* server. Defaults to JSON.parse.
*/
deserializer?: (e: MessageEvent) => T;
/**
* An Observer that watches when open events occur on the underlying web socket.
*/
openObserver?: NextObserver<Event>;
/**
* An Observer than watches when close events occur on the underlying webSocket
*/
closeObserver?: NextObserver<CloseEvent>;
/**
* An Observer that watches when a close is about to occur due to
* unsubscription.
*/
closingObserver?: NextObserver<void>;
/**
* A WebSocket constructor to use. This is useful for situations like using a
* WebSocket impl in Node (WebSocket is a DOM API), or for mocking a WebSocket
* for testing purposes
*/
WebSocketCtor?: { new(url: string, protocols?: string|string[]): WebSocket };
/** Sets the `binaryType` property of the underlying WebSocket. */
binaryType?: 'blob' | 'arraybuffer';
}
const DEFAULT_WEBSOCKET_CONFIG: WebSocketSubjectConfig<any> = {
url: '',
deserializer: (e: MessageEvent) => JSON.parse(e.data),
serializer: (value: any) => JSON.stringify(value),
};
const WEBSOCKETSUBJECT_INVALID_ERROR_OBJECT =
'WebSocketSubject.error must be called with an object with an error code, and an optional reason: { code: number, reason: string }';
export type WebSocketMessage = string | ArrayBuffer | Blob | ArrayBufferView;
export class WebSocketSubject<T> extends AnonymousSubject<T> {
private _config: WebSocketSubjectConfig<T>;
/** @deprecated This is an internal implementation detail, do not use. */
_output: Subject<T>;
private _socket: WebSocket;
constructor(urlConfigOrSource: string | WebSocketSubjectConfig<T> | Observable<T>, destination?: Observer<T>) {
super();
if (urlConfigOrSource instanceof Observable) {
this.destination = destination;
this.source = urlConfigOrSource as Observable<T>;
} else {
const config = this._config = { ...DEFAULT_WEBSOCKET_CONFIG };
this._output = new Subject<T>();
if (typeof urlConfigOrSource === 'string') {
config.url = urlConfigOrSource;
} else {
for (let key in urlConfigOrSource) {
if (urlConfigOrSource.hasOwnProperty(key)) {
config[key] = urlConfigOrSource[key];
}
}
}
if (!config.WebSocketCtor && WebSocket) {
config.WebSocketCtor = WebSocket;
} else if (!config.WebSocketCtor) {
throw new Error('no WebSocket constructor can be found');
}
this.destination = new ReplaySubject();
}
}
lift<R>(operator: Operator<T, R>): WebSocketSubject<R> {
const sock = new WebSocketSubject<R>(this._config as WebSocketSubjectConfig<any>, <any> this.destination);
sock.operator = operator;
sock.source = this;
return sock;
}
private _resetState() {
this._socket = null;
if (!this.source) {
this.destination = new ReplaySubject();
}
this._output = new Subject<T>();
}
/**
* Creates an {@link Observable}, that when subscribed to, sends a message,
* defined by the `subMsg` function, to the server over the socket to begin a
* subscription to data over that socket. Once data arrives, the
* `messageFilter` argument will be used to select the appropriate data for
* the resulting Observable. When teardown occurs, either due to
* unsubscription, completion or error, a message defined by the `unsubMsg`
* argument will be send to the server over the WebSocketSubject.
*
* @param subMsg A function to generate the subscription message to be sent to
* the server. This will still be processed by the serializer in the
* WebSocketSubject's config. (Which defaults to JSON serialization)
* @param unsubMsg A function to generate the unsubscription message to be
* sent to the server at teardown. This will still be processed by the
* serializer in the WebSocketSubject's config.
* @param messageFilter A predicate for selecting the appropriate messages
* from the server for the output stream.
*/
multiplex(subMsg: () => any, unsubMsg: () => any, messageFilter: (value: T) => boolean) {
const self = this;
return new Observable((observer: Observer<any>) => {
try {
self.next(subMsg());
} catch (err) {
observer.error(err);
}
const subscription = self.subscribe(x => {
try {
if (messageFilter(x)) {
observer.next(x);
}
} catch (err) {
observer.error(err);
}
},
err => observer.error(err),
() => observer.complete());
return () => {
try {
self.next(unsubMsg());
} catch (err) {
observer.error(err);
}
subscription.unsubscribe();
};
});
}
private _connectSocket() {
const { WebSocketCtor, protocol, url, binaryType } = this._config;
const observer = this._output;
let socket: WebSocket = null;
try {
socket = protocol ?
new WebSocketCtor(url, protocol) :
new WebSocketCtor(url);
this._socket = socket;
if (binaryType) {
this._socket.binaryType = binaryType;
}
} catch (e) {
observer.error(e);
return;
}
const subscription = new Subscription(() => {
this._socket = null;
if (socket && socket.readyState === 1) {
socket.close();
}
});
socket.onopen = (e: Event) => {
const { _socket } = this;
if (!_socket) {
socket.close();
this._resetState();
return;
}
const { openObserver } = this._config;
if (openObserver) {
openObserver.next(e);
}
const queue = this.destination;
this.destination = Subscriber.create<T>(
(x) => {
if (socket.readyState === 1) {
try {
const { serializer } = this._config;
socket.send(serializer(x));
} catch (e) {
this.destination.error(e);
}
}
},
(e) => {
const { closingObserver } = this._config;
if (closingObserver) {
closingObserver.next(undefined);
}
if (e && e.code) {
socket.close(e.code, e.reason);
} else {
observer.error(new TypeError(WEBSOCKETSUBJECT_INVALID_ERROR_OBJECT));
}
this._resetState();
},
() => {
const { closingObserver } = this._config;
if (closingObserver) {
closingObserver.next(undefined);
}
socket.close();
this._resetState();
}
) as Subscriber<any>;
if (queue && queue instanceof ReplaySubject) {
subscription.add((<ReplaySubject<T>>queue).subscribe(this.destination));
}
};
socket.onerror = (e: Event) => {
this._resetState();
observer.error(e);
};
socket.onclose = (e: CloseEvent) => {
this._resetState();
const { closeObserver } = this._config;
if (closeObserver) {
closeObserver.next(e);
}
if (e.wasClean) {
observer.complete();
} else {
observer.error(e);
}
};
socket.onmessage = (e: MessageEvent) => {
try {
const { deserializer } = this._config;
observer.next(deserializer(e));
} catch (err) {
observer.error(err);
}
};
}
/** @deprecated This is an internal implementation detail, do not use. */
_subscribe(subscriber: Subscriber<T>): Subscription {
const { source } = this;
if (source) {
return source.subscribe(subscriber);
}
if (!this._socket) {
this._connectSocket();
}
this._output.subscribe(subscriber);
subscriber.add(() => {
const { _socket } = this;
if (this._output.observers.length === 0) {
if (_socket && _socket.readyState === 1) {
_socket.close();
}
this._resetState();
}
});
return subscriber;
}
unsubscribe() {
const { _socket } = this;
if (_socket && _socket.readyState === 1) {
_socket.close();
}
this._resetState();
super.unsubscribe();
}
}

82
node_modules/rxjs/src/internal/observable/dom/ajax.ts generated vendored Normal file
View File

@ -0,0 +1,82 @@
import { AjaxObservable, AjaxCreationMethod } from './AjaxObservable';
/**
* There is an ajax operator on the Rx object.
*
* It creates an observable for an Ajax request with either a request object with
* url, headers, etc or a string for a URL.
*
*
* ## Using ajax() to fetch the response object that is being returned from API.
* ```ts
* import { ajax } from 'rxjs/ajax';
* import { map, catchError } from 'rxjs/operators';
* import { of } from 'rxjs';
*
* const obs$ = ajax(`https://api.github.com/users?per_page=5`).pipe(
* map(userResponse => console.log('users: ', userResponse)),
* catchError(error => {
* console.log('error: ', error);
* return of(error);
* })
* );
*
* ```
*
* ## Using ajax.getJSON() to fetch data from API.
* ```ts
* import { ajax } from 'rxjs/ajax';
* import { map, catchError } from 'rxjs/operators';
* import { of } from 'rxjs';
*
* const obs$ = ajax.getJSON(`https://api.github.com/users?per_page=5`).pipe(
* map(userResponse => console.log('users: ', userResponse)),
* catchError(error => {
* console.log('error: ', error);
* return of(error);
* })
* );
*
* ```
*
* ## Using ajax() with object as argument and method POST with a two seconds delay.
* ```ts
* import { ajax } from 'rxjs/ajax';
* import { of } from 'rxjs';
*
* const users = ajax({
* url: 'https://httpbin.org/delay/2',
* method: 'POST',
* headers: {
* 'Content-Type': 'application/json',
* 'rxjs-custom-header': 'Rxjs'
* },
* body: {
* rxjs: 'Hello World!'
* }
* }).pipe(
* map(response => console.log('response: ', response)),
* catchError(error => {
* console.log('error: ', error);
* return of(error);
* })
* );
*
* ```
*
* ## Using ajax() to fetch. An error object that is being returned from the request.
* ```ts
* import { ajax } from 'rxjs/ajax';
* import { map, catchError } from 'rxjs/operators';
* import { of } from 'rxjs';
*
* const obs$ = ajax(`https://api.github.com/404`).pipe(
* map(userResponse => console.log('users: ', userResponse)),
* catchError(error => {
* console.log('error: ', error);
* return of(error);
* })
* );
*
* ```
*/
export const ajax: AjaxCreationMethod = (() => AjaxObservable.create)();

99
node_modules/rxjs/src/internal/observable/dom/fetch.ts generated vendored Normal file
View File

@ -0,0 +1,99 @@
import { Observable } from '../../Observable';
/**
* Uses [the Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) to
* make an HTTP request.
*
* **WARNING** Parts of the fetch API are still experimental. `AbortController` is
* required for this implementation to work and use cancellation appropriately.
*
* Will automatically set up an internal [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)
* in order to teardown the internal `fetch` when the subscription tears down.
*
* If a `signal` is provided via the `init` argument, it will behave like it usually does with
* `fetch`. If the provided `signal` aborts, the error that `fetch` normally rejects with
* in that scenario will be emitted as an error from the observable.
*
* ### Basic Use
*
* ```ts
* import { of } from 'rxjs';
* import { fromFetch } from 'rxjs/fetch';
* import { switchMap, catchError } from 'rxjs/operators';
*
* const data$ = fromFetch('https://api.github.com/users?per_page=5').pipe(
* switchMap(response => {
* if (response.ok) {
* // OK return data
* return response.json();
* } else {
* // Server is returning a status requiring the client to try something else.
* return of({ error: true, message: `Error ${response.status}` });
* }
* }),
* catchError(err => {
* // Network or other error, handle appropriately
* console.error(err);
* return of({ error: true, message: err.message })
* })
* );
*
* data$.subscribe({
* next: result => console.log(result),
* complete: () => console.log('done')
* })
* ```
*
* @param input The resource you would like to fetch. Can be a url or a request object.
* @param init A configuration object for the fetch.
* [See MDN for more details](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters)
* @returns An Observable, that when subscribed to performs an HTTP request using the native `fetch`
* function. The {@link Subscription} is tied to an `AbortController` for the the fetch.
*/
export function fromFetch(input: string | Request, init?: RequestInit): Observable<Response> {
return new Observable<Response>(subscriber => {
const controller = new AbortController();
const signal = controller.signal;
let outerSignalHandler: () => void;
let abortable = true;
let unsubscribed = false;
if (init) {
// If a signal is provided, just have it teardown. It's a cancellation token, basically.
if (init.signal) {
if (init.signal.aborted) {
controller.abort();
} else {
outerSignalHandler = () => {
if (!signal.aborted) {
controller.abort();
}
};
init.signal.addEventListener('abort', outerSignalHandler);
}
}
init = { ...init, signal };
} else {
init = { signal };
}
fetch(input, init).then(response => {
abortable = false;
subscriber.next(response);
subscriber.complete();
}).catch(err => {
abortable = false;
if (!unsubscribed) {
// Only forward the error if it wasn't an abort.
subscriber.error(err);
}
});
return () => {
unsubscribed = true;
if (abortable) {
controller.abort();
}
};
});
}

View File

@ -0,0 +1,156 @@
import { WebSocketSubject, WebSocketSubjectConfig } from './WebSocketSubject';
/**
* Wrapper around the w3c-compatible WebSocket object provided by the browser.
*
* <span class="informal">{@link Subject} that communicates with a server via WebSocket</span>
*
* `webSocket` is a factory function that produces a `WebSocketSubject`,
* which can be used to make WebSocket connection with an arbitrary endpoint.
* `webSocket` accepts as an argument either a string with url of WebSocket endpoint, or an
* {@link WebSocketSubjectConfig} object for providing additional configuration, as
* well as Observers for tracking lifecycle of WebSocket connection.
*
* When `WebSocketSubject` is subscribed, it attempts to make a socket connection,
* unless there is one made already. This means that many subscribers will always listen
* on the same socket, thus saving resources. If however, two instances are made of `WebSocketSubject`,
* even if these two were provided with the same url, they will attempt to make separate
* connections. When consumer of a `WebSocketSubject` unsubscribes, socket connection is closed,
* only if there are no more subscribers still listening. If after some time a consumer starts
* subscribing again, connection is reestablished.
*
* Once connection is made, whenever a new message comes from the server, `WebSocketSubject` will emit that
* message as a value in the stream. By default, a message from the socket is parsed via `JSON.parse`. If you
* want to customize how deserialization is handled (if at all), you can provide custom `resultSelector`
* function in {@link WebSocketSubject}. When connection closes, stream will complete, provided it happened without
* any errors. If at any point (starting, maintaining or closing a connection) there is an error,
* stream will also error with whatever WebSocket API has thrown.
*
* By virtue of being a {@link Subject}, `WebSocketSubject` allows for receiving and sending messages from the server. In order
* to communicate with a connected endpoint, use `next`, `error` and `complete` methods. `next` sends a value to the server, so bear in mind
* that this value will not be serialized beforehand. Because of This, `JSON.stringify` will have to be called on a value by hand,
* before calling `next` with a result. Note also that if at the moment of nexting value
* there is no socket connection (for example no one is subscribing), those values will be buffered, and sent when connection
* is finally established. `complete` method closes socket connection. `error` does the same,
* as well as notifying the server that something went wrong via status code and string with details of what happened.
* Since status code is required in WebSocket API, `WebSocketSubject` does not allow, like regular `Subject`,
* arbitrary values being passed to the `error` method. It needs to be called with an object that has `code`
* property with status code number and optional `reason` property with string describing details
* of an error.
*
* Calling `next` does not affect subscribers of `WebSocketSubject` - they have no
* information that something was sent to the server (unless of course the server
* responds somehow to a message). On the other hand, since calling `complete` triggers
* an attempt to close socket connection. If that connection is closed without any errors, stream will
* complete, thus notifying all subscribers. And since calling `error` closes
* socket connection as well, just with a different status code for the server, if closing itself proceeds
* without errors, subscribed Observable will not error, as one might expect, but complete as usual. In both cases
* (calling `complete` or `error`), if process of closing socket connection results in some errors, *then* stream
* will error.
*
* **Multiplexing**
*
* `WebSocketSubject` has an additional operator, not found in other Subjects. It is called `multiplex` and it is
* used to simulate opening several socket connections, while in reality maintaining only one.
* For example, an application has both chat panel and real-time notifications about sport news. Since these are two distinct functions,
* it would make sense to have two separate connections for each. Perhaps there could even be two separate services with WebSocket
* endpoints, running on separate machines with only GUI combining them together. Having a socket connection
* for each functionality could become too resource expensive. It is a common pattern to have single
* WebSocket endpoint that acts as a gateway for the other services (in this case chat and sport news services).
* Even though there is a single connection in a client app, having the ability to manipulate streams as if it
* were two separate sockets is desirable. This eliminates manually registering and unregistering in a gateway for
* given service and filter out messages of interest. This is exactly what `multiplex` method is for.
*
* Method accepts three parameters. First two are functions returning subscription and unsubscription messages
* respectively. These are messages that will be sent to the server, whenever consumer of resulting Observable
* subscribes and unsubscribes. Server can use them to verify that some kind of messages should start or stop
* being forwarded to the client. In case of the above example application, after getting subscription message with proper identifier,
* gateway server can decide that it should connect to real sport news service and start forwarding messages from it.
* Note that both messages will be sent as returned by the functions, they are by default serialized using JSON.stringify, just
* as messages pushed via `next`. Also bear in mind that these messages will be sent on *every* subscription and
* unsubscription. This is potentially dangerous, because one consumer of an Observable may unsubscribe and the server
* might stop sending messages, since it got unsubscription message. This needs to be handled
* on the server or using {@link publish} on a Observable returned from 'multiplex'.
*
* Last argument to `multiplex` is a `messageFilter` function which should return a boolean. It is used to filter out messages
* sent by the server to only those that belong to simulated WebSocket stream. For example, server might mark these
* messages with some kind of string identifier on a message object and `messageFilter` would return `true`
* if there is such identifier on an object emitted by the socket. Messages which returns `false` in `messageFilter` are simply skipped,
* and are not passed down the stream.
*
* Return value of `multiplex` is an Observable with messages incoming from emulated socket connection. Note that this
* is not a `WebSocketSubject`, so calling `next` or `multiplex` again will fail. For pushing values to the
* server, use root `WebSocketSubject`.
*
* ### Examples
* #### Listening for messages from the server
* ```ts
* import { webSocket } from "rxjs/webSocket";
* const subject = webSocket("ws://localhost:8081");
*
* subject.subscribe(
* msg => console.log('message received: ' + msg), // Called whenever there is a message from the server.
* err => console.log(err), // Called if at any point WebSocket API signals some kind of error.
* () => console.log('complete') // Called when connection is closed (for whatever reason).
* );
* ```
*
* #### Pushing messages to the server
* ```ts
* import { webSocket } from "rxjs/webSocket";
* const subject = webSocket('ws://localhost:8081');
*
* subject.subscribe();
* // Note that at least one consumer has to subscribe to the created subject - otherwise "nexted" values will be just buffered and not sent,
* // since no connection was established!
*
* subject.next({message: 'some message'});
* // This will send a message to the server once a connection is made. Remember value is serialized with JSON.stringify by default!
*
* subject.complete(); // Closes the connection.
*
* subject.error({code: 4000, reason: 'I think our app just broke!'});
* // Also closes the connection, but let's the server know that this closing is caused by some error.
* ```
*
* #### Multiplexing WebSocket
* ```ts
* import { webSocket } from "rxjs/webSocket";
* const subject = webSocket('ws://localhost:8081');
*
* const observableA = subject.multiplex(
* () => ({subscribe: 'A'}), // When server gets this message, it will start sending messages for 'A'...
* () => ({unsubscribe: 'A'}), // ...and when gets this one, it will stop.
* message => message.type === 'A' // If the function returns `true` message is passed down the stream. Skipped if the function returns false.
* );
*
* const observableB = subject.multiplex( // And the same goes for 'B'.
* () => ({subscribe: 'B'}),
* () => ({unsubscribe: 'B'}),
* message => message.type === 'B'
* );
*
* const subA = observableA.subscribe(messageForA => console.log(messageForA));
* // At this moment WebSocket connection is established. Server gets '{"subscribe": "A"}' message and starts sending messages for 'A',
* // which we log here.
*
* const subB = observableB.subscribe(messageForB => console.log(messageForB));
* // Since we already have a connection, we just send '{"subscribe": "B"}' message to the server. It starts sending messages for 'B',
* // which we log here.
*
* subB.unsubscribe();
* // Message '{"unsubscribe": "B"}' is sent to the server, which stops sending 'B' messages.
*
* subA.unsubscribe();
* // Message '{"unsubscribe": "A"}' makes the server stop sending messages for 'A'. Since there is no more subscribers to root Subject,
* // socket connection closes.
* ```
*
*
* @param {string|WebSocketSubjectConfig} urlConfigOrSource The WebSocket endpoint as an url or an object with
* configuration and additional Observers.
* @return {WebSocketSubject} Subject which allows to both send and receive messages via WebSocket connection.
*/
export function webSocket<T>(urlConfigOrSource: string | WebSocketSubjectConfig<T>): WebSocketSubject<T> {
return new WebSocketSubject<T>(urlConfigOrSource);
}

68
node_modules/rxjs/src/internal/observable/empty.ts generated vendored Normal file
View File

@ -0,0 +1,68 @@
import { Observable } from '../Observable';
import { SchedulerLike } from '../types';
/**
* The same Observable instance returned by any call to {@link empty} without a
* `scheduler`. It is preferrable to use this over `empty()`.
*/
export const EMPTY = new Observable<never>(subscriber => subscriber.complete());
/**
* 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>
*
* ![](empty.png)
*
* 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}.
*
* ## Examples
* ### Emit the number 7, then complete
* ```ts
* import { empty } from 'rxjs';
* import { startWith } from 'rxjs/operators';
*
* const result = empty().pipe(startWith(7));
* result.subscribe(x => console.log(x));
* ```
*
* ### Map and flatten only odd numbers to the sequence 'a', 'b', 'c'
* ```ts
* import { empty, interval, of } from 'rxjs';
* import { mergeMap } from 'rxjs/operators';
*
* const interval$ = interval(1000);
* const result = interval$.pipe(
* mergeMap(x => x % 2 === 1 ? of('a', 'b', 'c') : empty()),
* );
* result.subscribe(x => console.log(x));
*
* // Results in the following to the console:
* // x is equal to the count on the interval eg(0,1,2,3,...)
* // x will occur every 1000ms
* // if x % 2 is equal to 1 print abc
* // if x % 2 is not equal to 1 nothing will be output
* ```
*
* @see {@link Observable}
* @see {@link never}
* @see {@link of}
* @see {@link throwError}
*
* @param scheduler A {@link SchedulerLike} to use for scheduling
* the emission of the complete notification.
* @return An "empty" Observable: emits only the complete
* notification.
* @deprecated Deprecated in favor of using {@link EMPTY} constant, or {@link scheduled} (e.g. `scheduled([], scheduler)`)
*/
export function empty(scheduler?: SchedulerLike) {
return scheduler ? emptyScheduled(scheduler) : EMPTY;
}
function emptyScheduled(scheduler: SchedulerLike) {
return new Observable<never>(subscriber => scheduler.schedule(() => subscriber.complete()));
}

204
node_modules/rxjs/src/internal/observable/forkJoin.ts generated vendored Normal file
View File

@ -0,0 +1,204 @@
import { Observable } from '../Observable';
import { ObservableInput, ObservedValuesFromArray, ObservedValueOf, SubscribableOrPromise } from '../types';
import { isArray } from '../util/isArray';
import { map } from '../operators/map';
import { isObject } from '../util/isObject';
import { isObservable } from '../util/isObservable';
import { from } from './from';
/* tslint:disable:max-line-length */
// forkJoin(a$, b$, c$)
/** @deprecated Use the version that takes an array of Observables instead */
export function forkJoin<T>(v1: SubscribableOrPromise<T>): Observable<[T]>;
/** @deprecated Use the version that takes an array of Observables instead */
export function forkJoin<T, T2>(v1: ObservableInput<T>, v2: ObservableInput<T2>): Observable<[T, T2]>;
/** @deprecated Use the version that takes an array of Observables instead */
export function forkJoin<T, T2, T3>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>): Observable<[T, T2, T3]>;
/** @deprecated Use the version that takes an array of Observables instead */
export function forkJoin<T, T2, T3, T4>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>): Observable<[T, T2, T3, T4]>;
/** @deprecated Use the version that takes an array of Observables instead */
export function forkJoin<T, T2, T3, T4, T5>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, v5: ObservableInput<T5>): Observable<[T, T2, T3, T4, T5]>;
/** @deprecated Use the version that takes an array of Observables instead */
export function forkJoin<T, T2, T3, T4, T5, T6>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, v5: ObservableInput<T5>, v6: ObservableInput<T6>): Observable<[T, T2, T3, T4, T5, T6]>;
// forkJoin([a$, b$, c$]);
// TODO(benlesh): Uncomment for TS 3.0
// export function forkJoin(sources: []): Observable<never>;
export function forkJoin<A>(sources: [ObservableInput<A>]): Observable<[A]>;
export function forkJoin<A, B>(sources: [ObservableInput<A>, ObservableInput<B>]): Observable<[A, B]>;
export function forkJoin<A, B, C>(sources: [ObservableInput<A>, ObservableInput<B>, ObservableInput<C>]): Observable<[A, B, C]>;
export function forkJoin<A, B, C, D>(sources: [ObservableInput<A>, ObservableInput<B>, ObservableInput<C>, ObservableInput<D>]): Observable<[A, B, C, D]>;
export function forkJoin<A, B, C, D, E>(sources: [ObservableInput<A>, ObservableInput<B>, ObservableInput<C>, ObservableInput<D>, ObservableInput<E>]): Observable<[A, B, C, D, E]>;
export function forkJoin<A, B, C, D, E, F>(sources: [ObservableInput<A>, ObservableInput<B>, ObservableInput<C>, ObservableInput<D>, ObservableInput<E>, ObservableInput<F>]): Observable<[A, B, C, D, E, F]>;
export function forkJoin<A extends ObservableInput<any>[]>(sources: A): Observable<ObservedValuesFromArray<A>[]>;
// forkJoin({})
export function forkJoin(sourcesObject: {}): Observable<never>;
export function forkJoin<T, K extends keyof T>(sourcesObject: T): Observable<{ [K in keyof T]: ObservedValueOf<T[K]> }>;
/** @deprecated resultSelector is deprecated, pipe to map instead */
export function forkJoin(...args: Array<ObservableInput<any>|Function>): Observable<any>;
/** @deprecated Use the version that takes an array of Observables instead */
export function forkJoin<T>(...sources: ObservableInput<T>[]): Observable<T[]>;
/* tslint:enable:max-line-length */
/**
* Accepts an `Array` of {@link ObservableInput} or a dictionary `Object` of {@link ObservableInput} and returns
* an {@link Observable} that emits either an array of values in the exact same order as the passed array,
* or a dictionary of values in the same shape as the passed dictionary.
*
* <span class="informal">Wait for Observables to complete and then combine last values they emitted.</span>
*
* ![](forkJoin.png)
*
* `forkJoin` is an operator that takes any number of input observables which can be passed either as an array
* or a dictionary of input observables. If no input observables are provided, resulting stream will complete
* immediately.
*
* `forkJoin` will wait for all passed observables to complete and then it will emit an array or an object with last
* values from corresponding observables.
*
* If you pass an array of `n` observables to the operator, resulting
* array will have `n` values, where first value is the last thing emitted by the first observable,
* second value is the last thing emitted by the second observable and so on.
*
* If you pass a dictionary of observables to the operator, resulting
* objects will have the same keys as the dictionary passed, with their last values they've emitted
* located at the corresponding key.
*
* That means `forkJoin` will not emit more than once and it will complete after that. If you need to emit combined
* values not only at the end of lifecycle of passed observables, but also throughout it, try out {@link combineLatest}
* or {@link zip} instead.
*
* In order for resulting array to have the same length as the number of input observables, whenever any of
* that observables completes without emitting any value, `forkJoin` will complete at that moment as well
* and it will not emit anything either, even if it already has some last values from other observables.
* Conversely, if there is an observable that never completes, `forkJoin` will never complete as well,
* unless at any point some other observable completes without emitting value, which brings us back to
* the previous case. Overall, in order for `forkJoin` to emit a value, all observables passed as arguments
* have to emit something at least once and complete.
*
* If any input observable errors at some point, `forkJoin` will error as well and all other observables
* will be immediately unsubscribed.
*
* Optionally `forkJoin` accepts project function, that will be called with values which normally
* would land in emitted array. Whatever is returned by project function, will appear in output
* observable instead. This means that default project can be thought of as a function that takes
* all its arguments and puts them into an array. Note that project function will be called only
* when output observable is supposed to emit a result.
*
* ## Examples
*
* ### Use forkJoin with a dictionary of observable inputs
* ```ts
* import { forkJoin, of, timer } from 'rxjs';
*
* const observable = forkJoin({
* foo: of(1, 2, 3, 4),
* bar: Promise.resolve(8),
* baz: timer(4000),
* });
* observable.subscribe({
* next: value => console.log(value),
* complete: () => console.log('This is how it ends!'),
* });
*
* // Logs:
* // { foo: 4, bar: 8, baz: 0 } after 4 seconds
* // "This is how it ends!" immediately after
* ```
*
* ### Use forkJoin with an array of observable inputs
* ```ts
* import { forkJoin, of } from 'rxjs';
*
* const observable = forkJoin([
* of(1, 2, 3, 4),
* Promise.resolve(8),
* timer(4000),
* ]);
* observable.subscribe({
* next: value => console.log(value),
* complete: () => console.log('This is how it ends!'),
* });
*
* // Logs:
* // [4, 8, 0] after 4 seconds
* // "This is how it ends!" immediately after
* ```
*
* @see {@link combineLatest}
* @see {@link zip}
*
* @param {...ObservableInput} sources Any number of Observables provided either as an array or as an arguments
* passed directly to the operator.
* @param {function} [project] Function that takes values emitted by input Observables and returns value
* that will appear in resulting Observable instead of default array.
* @return {Observable} Observable emitting either an array of last values emitted by passed Observables
* or value from project function.
*/
export function forkJoin(
...sources: any[]
): Observable<any> {
if (sources.length === 1) {
const first = sources[0];
if (isArray(first)) {
return forkJoinInternal(first, null);
}
// TODO(benlesh): isObservable check will not be necessary when deprecated path is removed.
if (isObject(first) && Object.getPrototypeOf(first) === Object.prototype) {
const keys = Object.keys(first);
return forkJoinInternal(keys.map(key => first[key]), keys);
}
}
// DEPRECATED PATHS BELOW HERE
if (typeof sources[sources.length - 1] === 'function') {
const resultSelector = sources.pop() as Function;
sources = (sources.length === 1 && isArray(sources[0])) ? sources[0] : sources;
return forkJoinInternal(sources, null).pipe(
map((args: any[]) => resultSelector(...args))
);
}
return forkJoinInternal(sources, null);
}
function forkJoinInternal(sources: ObservableInput<any>[], keys: string[] | null): Observable<any> {
return new Observable(subscriber => {
const len = sources.length;
if (len === 0) {
subscriber.complete();
return;
}
const values = new Array(len);
let completed = 0;
let emitted = 0;
for (let i = 0; i < len; i++) {
const source = from(sources[i]);
let hasValue = false;
subscriber.add(source.subscribe({
next: value => {
if (!hasValue) {
hasValue = true;
emitted++;
}
values[i] = value;
},
error: err => subscriber.error(err),
complete: () => {
completed++;
if (completed === len || !hasValue) {
if (emitted === len) {
subscriber.next(keys ?
keys.reduce((result, key, i) => (result[key] = values[i], result), {}) :
values);
}
subscriber.complete();
}
}
}));
}
});
}

118
node_modules/rxjs/src/internal/observable/from.ts generated vendored Normal file
View File

@ -0,0 +1,118 @@
import { Observable } from '../Observable';
import { subscribeTo } from '../util/subscribeTo';
import { ObservableInput, SchedulerLike, ObservedValueOf } from '../types';
import { scheduled } from '../scheduled/scheduled';
export function from<O extends ObservableInput<any>>(input: O): Observable<ObservedValueOf<O>>;
/** @deprecated use {@link scheduled} instead. */
export function from<O extends ObservableInput<any>>(input: O, scheduler: SchedulerLike): Observable<ObservedValueOf<O>>;
/**
* Creates an Observable from an Array, an array-like object, a Promise, an iterable object, or an Observable-like object.
*
* <span class="informal">Converts almost anything to an Observable.</span>
*
* ![](from.png)
*
* `from` converts various other objects and data types into Observables. It also converts a Promise, an array-like, or an
* <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#iterable" target="_blank">iterable</a>
* object into an Observable that emits the items in that promise, array, or iterable. A String, in this context, is treated
* as an array of characters. Observable-like objects (contains a function named with the ES2015 Symbol for Observable) can also be
* converted through this operator.
*
* ## Examples
*
* ### Converts an array to an Observable
*
* ```ts
* import { from } from 'rxjs';
*
* const array = [10, 20, 30];
* const result = from(array);
*
* result.subscribe(x => console.log(x));
*
* // Logs:
* // 10
* // 20
* // 30
* ```
*
* ---
*
* ### Convert an infinite iterable (from a generator) to an Observable
*
* ```ts
* import { from } from 'rxjs';
* import { take } from 'rxjs/operators';
*
* function* generateDoubles(seed) {
* let i = seed;
* while (true) {
* yield i;
* i = 2 * i; // double it
* }
* }
*
* const iterator = generateDoubles(3);
* const result = from(iterator).pipe(take(10));
*
* result.subscribe(x => console.log(x));
*
* // Logs:
* // 3
* // 6
* // 12
* // 24
* // 48
* // 96
* // 192
* // 384
* // 768
* // 1536
* ```
*
* ---
*
* ### With async scheduler
*
* ```ts
* import { from, asyncScheduler } from 'rxjs';
*
* console.log('start');
*
* const array = [10, 20, 30];
* const result = from(array, asyncScheduler);
*
* result.subscribe(x => console.log(x));
*
* console.log('end');
*
* // Logs:
* // start
* // end
* // 10
* // 20
* // 30
* ```
*
* @see {@link fromEvent}
* @see {@link fromEventPattern}
*
* @param {ObservableInput<T>} A subscription object, a Promise, an Observable-like,
* an Array, an iterable, or an array-like object to be converted.
* @param {SchedulerLike} An optional {@link SchedulerLike} on which to schedule the emission of values.
* @return {Observable<T>}
* @name from
* @owner Observable
*/
export function from<T>(input: ObservableInput<T>, scheduler?: SchedulerLike): Observable<T> {
if (!scheduler) {
if (input instanceof Observable) {
return input;
}
return new Observable<T>(subscribeTo(input));
} else {
return scheduled(input, scheduler);
}
}

12
node_modules/rxjs/src/internal/observable/fromArray.ts generated vendored Normal file
View File

@ -0,0 +1,12 @@
import { Observable } from '../Observable';
import { SchedulerLike } from '../types';
import { subscribeToArray } from '../util/subscribeToArray';
import { scheduleArray } from '../scheduled/scheduleArray';
export function fromArray<T>(input: ArrayLike<T>, scheduler?: SchedulerLike) {
if (!scheduler) {
return new Observable<T>(subscribeToArray(input));
} else {
return scheduleArray(input, scheduler);
}
}

245
node_modules/rxjs/src/internal/observable/fromEvent.ts generated vendored Normal file
View File

@ -0,0 +1,245 @@
import { Observable } from '../Observable';
import { isArray } from '../util/isArray';
import { isFunction } from '../util/isFunction';
import { Subscriber } from '../Subscriber';
import { map } from '../operators/map';
const toString: Function = (() => Object.prototype.toString)();
export interface NodeStyleEventEmitter {
addListener: (eventName: string | symbol, handler: NodeEventHandler) => this;
removeListener: (eventName: string | symbol, handler: NodeEventHandler) => this;
}
export type NodeEventHandler = (...args: any[]) => void;
// For APIs that implement `addListener` and `removeListener` methods that may
// not use the same arguments or return EventEmitter values
// such as React Native
export interface NodeCompatibleEventEmitter {
addListener: (eventName: string, handler: NodeEventHandler) => void | {};
removeListener: (eventName: string, handler: NodeEventHandler) => void | {};
}
export interface JQueryStyleEventEmitter {
on: (eventName: string, handler: Function) => void;
off: (eventName: string, handler: Function) => void;
}
export interface HasEventTargetAddRemove<E> {
addEventListener(type: string, listener: ((evt: E) => void) | null, options?: boolean | AddEventListenerOptions): void;
removeEventListener(type: string, listener?: ((evt: E) => void) | null, options?: EventListenerOptions | boolean): void;
}
export type EventTargetLike<T> = HasEventTargetAddRemove<T> | NodeStyleEventEmitter | NodeCompatibleEventEmitter | JQueryStyleEventEmitter;
export type FromEventTarget<T> = EventTargetLike<T> | ArrayLike<EventTargetLike<T>>;
export interface EventListenerOptions {
capture?: boolean;
passive?: boolean;
once?: boolean;
}
export interface AddEventListenerOptions extends EventListenerOptions {
once?: boolean;
passive?: boolean;
}
/* tslint:disable:max-line-length */
export function fromEvent<T>(target: FromEventTarget<T>, eventName: string): Observable<T>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function fromEvent<T>(target: FromEventTarget<T>, eventName: string, resultSelector: (...args: any[]) => T): Observable<T>;
export function fromEvent<T>(target: FromEventTarget<T>, eventName: string, options: EventListenerOptions): Observable<T>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function fromEvent<T>(target: FromEventTarget<T>, eventName: string, options: EventListenerOptions, resultSelector: (...args: any[]) => T): Observable<T>;
/* tslint:enable:max-line-length */
/**
* Creates an Observable that emits events of a specific type coming from the
* given event target.
*
* <span class="informal">Creates an Observable from DOM events, or Node.js
* EventEmitter events or others.</span>
*
* ![](fromEvent.png)
*
* `fromEvent` accepts as a first argument event target, which is an object with methods
* for registering event handler functions. As a second argument it takes string that indicates
* type of event we want to listen for. `fromEvent` supports selected types of event targets,
* which are described in detail below. If your event target does not match any of the ones listed,
* you should use {@link fromEventPattern}, which can be used on arbitrary APIs.
* When it comes to APIs supported by `fromEvent`, their methods for adding and removing event
* handler functions have different names, but they all accept a string describing event type
* and function itself, which will be called whenever said event happens.
*
* Every time resulting Observable is subscribed, event handler function will be registered
* to event target on given event type. When that event fires, value
* passed as a first argument to registered function will be emitted by output Observable.
* When Observable is unsubscribed, function will be unregistered from event target.
*
* Note that if event target calls registered function with more than one argument, second
* and following arguments will not appear in resulting stream. In order to get access to them,
* you can pass to `fromEvent` optional project function, which will be called with all arguments
* passed to event handler. Output Observable will then emit value returned by project function,
* instead of the usual value.
*
* Remember that event targets listed below are checked via duck typing. It means that
* no matter what kind of object you have and no matter what environment you work in,
* you can safely use `fromEvent` on that object if it exposes described methods (provided
* of course they behave as was described above). So for example if Node.js library exposes
* event target which has the same method names as DOM EventTarget, `fromEvent` is still
* a good choice.
*
* If the API you use is more callback then event handler oriented (subscribed
* callback function fires only once and thus there is no need to manually
* unregister it), you should use {@link bindCallback} or {@link bindNodeCallback}
* instead.
*
* `fromEvent` supports following types of event targets:
*
* **DOM EventTarget**
*
* This is an object with `addEventListener` and `removeEventListener` methods.
*
* In the browser, `addEventListener` accepts - apart from event type string and event
* handler function arguments - optional third parameter, which is either an object or boolean,
* both used for additional configuration how and when passed function will be called. When
* `fromEvent` is used with event target of that type, you can provide this values
* as third parameter as well.
*
* **Node.js EventEmitter**
*
* An object with `addListener` and `removeListener` methods.
*
* **JQuery-style event target**
*
* An object with `on` and `off` methods
*
* **DOM NodeList**
*
* List of DOM Nodes, returned for example by `document.querySelectorAll` or `Node.childNodes`.
*
* Although this collection is not event target in itself, `fromEvent` will iterate over all Nodes
* it contains and install event handler function in every of them. When returned Observable
* is unsubscribed, function will be removed from all Nodes.
*
* **DOM HtmlCollection**
*
* Just as in case of NodeList it is a collection of DOM nodes. Here as well event handler function is
* installed and removed in each of elements.
*
*
* ## Examples
* ### Emits clicks happening on the DOM document
* ```ts
* import { fromEvent } from 'rxjs';
*
* const clicks = fromEvent(document, 'click');
* clicks.subscribe(x => console.log(x));
*
* // Results in:
* // MouseEvent object logged to console every time a click
* // occurs on the document.
* ```
*
* ### Use addEventListener with capture option
* ```ts
* import { fromEvent } from 'rxjs';
*
* const clicksInDocument = fromEvent(document, 'click', true); // note optional configuration parameter
* // which will be passed to addEventListener
* const clicksInDiv = fromEvent(someDivInDocument, 'click');
*
* clicksInDocument.subscribe(() => console.log('document'));
* clicksInDiv.subscribe(() => console.log('div'));
*
* // By default events bubble UP in DOM tree, so normally
* // when we would click on div in document
* // "div" would be logged first and then "document".
* // Since we specified optional `capture` option, document
* // will catch event when it goes DOWN DOM tree, so console
* // will log "document" and then "div".
* ```
*
* @see {@link bindCallback}
* @see {@link bindNodeCallback}
* @see {@link fromEventPattern}
*
* @param {FromEventTarget<T>} target The DOM EventTarget, Node.js
* EventEmitter, JQuery-like event target, NodeList or HTMLCollection to attach the event handler to.
* @param {string} eventName The event name of interest, being emitted by the
* `target`.
* @param {EventListenerOptions} [options] Options to pass through to addEventListener
* @return {Observable<T>}
* @name fromEvent
*/
export function fromEvent<T>(
target: FromEventTarget<T>,
eventName: string,
options?: EventListenerOptions | ((...args: any[]) => T),
resultSelector?: ((...args: any[]) => T)
): Observable<T> {
if (isFunction(options)) {
// DEPRECATED PATH
resultSelector = options;
options = undefined;
}
if (resultSelector) {
// DEPRECATED PATH
return fromEvent<T>(target, eventName, <EventListenerOptions | undefined>options).pipe(
map(args => isArray(args) ? resultSelector(...args) : resultSelector(args))
);
}
return new Observable<T>(subscriber => {
function handler(e: T) {
if (arguments.length > 1) {
subscriber.next(Array.prototype.slice.call(arguments));
} else {
subscriber.next(e);
}
}
setupSubscription(target, eventName, handler, subscriber, options as EventListenerOptions);
});
}
function setupSubscription<T>(sourceObj: FromEventTarget<T>, eventName: string,
handler: (...args: any[]) => void, subscriber: Subscriber<T>,
options?: EventListenerOptions) {
let unsubscribe: () => void;
if (isEventTarget(sourceObj)) {
const source = sourceObj;
sourceObj.addEventListener(eventName, handler, options);
unsubscribe = () => source.removeEventListener(eventName, handler, options);
} else if (isJQueryStyleEventEmitter(sourceObj)) {
const source = sourceObj;
sourceObj.on(eventName, handler);
unsubscribe = () => source.off(eventName, handler);
} else if (isNodeStyleEventEmitter(sourceObj)) {
const source = sourceObj;
sourceObj.addListener(eventName, handler as NodeEventHandler);
unsubscribe = () => source.removeListener(eventName, handler as NodeEventHandler);
} else if (sourceObj && (sourceObj as any).length) {
for (let i = 0, len = (sourceObj as any).length; i < len; i++) {
setupSubscription(sourceObj[i], eventName, handler, subscriber, options);
}
} else {
throw new TypeError('Invalid event target');
}
subscriber.add(unsubscribe);
}
function isNodeStyleEventEmitter(sourceObj: any): sourceObj is NodeStyleEventEmitter {
return sourceObj && typeof sourceObj.addListener === 'function' && typeof sourceObj.removeListener === 'function';
}
function isJQueryStyleEventEmitter(sourceObj: any): sourceObj is JQueryStyleEventEmitter {
return sourceObj && typeof sourceObj.on === 'function' && typeof sourceObj.off === 'function';
}
function isEventTarget(sourceObj: any): sourceObj is HasEventTargetAddRemove<any> {
return sourceObj && typeof sourceObj.addEventListener === 'function' && typeof sourceObj.removeEventListener === 'function';
}

View File

@ -0,0 +1,169 @@
import { Observable } from '../Observable';
import { isArray } from '../util/isArray';
import { isFunction } from '../util/isFunction';
import { NodeEventHandler } from './fromEvent';
import { map } from '../operators/map';
/* tslint:disable:max-line-length */
export function fromEventPattern<T>(addHandler: (handler: NodeEventHandler) => any, removeHandler?: (handler: NodeEventHandler, signal?: any) => void): Observable<T>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function fromEventPattern<T>(addHandler: (handler: NodeEventHandler) => any, removeHandler?: (handler: NodeEventHandler, signal?: any) => void, resultSelector?: (...args: any[]) => T): Observable<T>;
/* tslint:enable:max-line-length */
/**
* Creates an Observable from an arbitrary API for registering event handlers.
*
* <span class="informal">When that method for adding event handler was something {@link fromEvent}
* was not prepared for.</span>
*
* ![](fromEventPattern.png)
*
* `fromEventPattern` allows you to convert into an Observable any API that supports registering handler functions
* for events. It is similar to {@link fromEvent}, but far
* more flexible. In fact, all use cases of {@link fromEvent} could be easily handled by
* `fromEventPattern` (although in slightly more verbose way).
*
* This operator accepts as a first argument an `addHandler` function, which will be injected with
* handler parameter. That handler is actually an event handler function that you now can pass
* to API expecting it. `addHandler` will be called whenever Observable
* returned by the operator is subscribed, so registering handler in API will not
* necessarily happen when `fromEventPattern` is called.
*
* After registration, every time an event that we listen to happens,
* Observable returned by `fromEventPattern` will emit value that event handler
* function was called with. Note that if event handler was called with more
* then one argument, second and following arguments will not appear in the Observable.
*
* If API you are using allows to unregister event handlers as well, you can pass to `fromEventPattern`
* another function - `removeHandler` - as a second parameter. It will be injected
* with the same handler function as before, which now you can use to unregister
* it from the API. `removeHandler` will be called when consumer of resulting Observable
* unsubscribes from it.
*
* In some APIs unregistering is actually handled differently. Method registering an event handler
* returns some kind of token, which is later used to identify which function should
* be unregistered or it itself has method that unregisters event handler.
* If that is the case with your API, make sure token returned
* by registering method is returned by `addHandler`. Then it will be passed
* as a second argument to `removeHandler`, where you will be able to use it.
*
* If you need access to all event handler parameters (not only the first one),
* or you need to transform them in any way, you can call `fromEventPattern` with optional
* third parameter - project function which will accept all arguments passed to
* event handler when it is called. Whatever is returned from project function will appear on
* resulting stream instead of usual event handlers first argument. This means
* that default project can be thought of as function that takes its first parameter
* and ignores the rest.
*
* ## Example
* ### Emits clicks happening on the DOM document
*
* ```ts
* import { fromEventPattern } from 'rxjs';
*
* function addClickHandler(handler) {
* document.addEventListener('click', handler);
* }
*
* function removeClickHandler(handler) {
* document.removeEventListener('click', handler);
* }
*
* const clicks = fromEventPattern(
* addClickHandler,
* removeClickHandler
* );
* clicks.subscribe(x => console.log(x));
*
* // Whenever you click anywhere in the browser, DOM MouseEvent
* // object will be logged.
* ```
*
* ## Example
* ### Use with API that returns cancellation token
*
* ```ts
* import { fromEventPattern } from 'rxjs';
*
* const token = someAPI.registerEventHandler(function() {});
* someAPI.unregisterEventHandler(token); // this APIs cancellation method accepts
* // not handler itself, but special token.
*
* const someAPIObservable = fromEventPattern(
* function(handler) { return someAPI.registerEventHandler(handler); }, // Note that we return the token here...
* function(handler, token) { someAPI.unregisterEventHandler(token); } // ...to then use it here.
* );
* ```
*
* ## Example
* ### Use with project function
*
* ```ts
* import { fromEventPattern } from 'rxjs';
*
* someAPI.registerEventHandler((eventType, eventMessage) => {
* console.log(eventType, eventMessage); // Logs "EVENT_TYPE" "EVENT_MESSAGE" to console.
* });
*
* const someAPIObservable = fromEventPattern(
* handler => someAPI.registerEventHandler(handler),
* handler => someAPI.unregisterEventHandler(handler)
* (eventType, eventMessage) => eventType + " --- " + eventMessage // without that function only "EVENT_TYPE"
* ); // would be emitted by the Observable
*
* someAPIObservable.subscribe(value => console.log(value));
*
* // Logs:
* // "EVENT_TYPE --- EVENT_MESSAGE"
* ```
*
* @see {@link fromEvent}
* @see {@link bindCallback}
* @see {@link bindNodeCallback}
*
* @param {function(handler: Function): any} addHandler A function that takes
* a `handler` function as argument and attaches it somehow to the actual
* source of events.
* @param {function(handler: Function, token?: any): void} [removeHandler] A function that
* takes a `handler` function as an argument and removes it from the event source. If `addHandler`
* returns some kind of token, `removeHandler` function will have it as a second parameter.
* @param {function(...args: any): T} [project] A function to
* transform results. It takes the arguments from the event handler and
* should return a single value.
* @return {Observable<T>} Observable which, when an event happens, emits first parameter
* passed to registered event handler. Alternatively it emits whatever project function returns
* at that moment.
* @static true
* @name fromEventPattern
* @owner Observable
*/
export function fromEventPattern<T>(addHandler: (handler: NodeEventHandler) => any,
removeHandler?: (handler: NodeEventHandler, signal?: any) => void,
resultSelector?: (...args: any[]) => T): Observable<T | T[]> {
if (resultSelector) {
// DEPRECATED PATH
return fromEventPattern<T>(addHandler, removeHandler).pipe(
map(args => isArray(args) ? resultSelector(...args) : resultSelector(args))
);
}
return new Observable<T | T[]>(subscriber => {
const handler = (...e: T[]) => subscriber.next(e.length === 1 ? e[0] : e);
let retValue: any;
try {
retValue = addHandler(handler);
} catch (err) {
subscriber.error(err);
return undefined;
}
if (!isFunction(removeHandler)) {
return undefined;
}
return () => removeHandler(handler, retValue) ;
});
}

View File

@ -0,0 +1,15 @@
import { Observable } from '../Observable';
import { SchedulerLike } from '../types';
import { subscribeToIterable } from '../util/subscribeToIterable';
import { scheduleIterable } from '../scheduled/scheduleIterable';
export function fromIterable<T>(input: Iterable<T>, scheduler?: SchedulerLike) {
if (!input) {
throw new Error('Iterable cannot be null');
}
if (!scheduler) {
return new Observable<T>(subscribeToIterable(input));
} else {
return scheduleIterable(input, scheduler);
}
}

View File

@ -0,0 +1,12 @@
import { Observable } from '../Observable';
import { subscribeToObservable } from '../util/subscribeToObservable';
import { InteropObservable, SchedulerLike } from '../types';
import { scheduleObservable } from '../scheduled/scheduleObservable';
export function fromObservable<T>(input: InteropObservable<T>, scheduler?: SchedulerLike) {
if (!scheduler) {
return new Observable<T>(subscribeToObservable(input));
} else {
return scheduleObservable(input, scheduler);
}
}

View File

@ -0,0 +1,12 @@
import { Observable } from '../Observable';
import { SchedulerLike } from '../types';
import { subscribeToPromise } from '../util/subscribeToPromise';
import { schedulePromise } from '../scheduled/schedulePromise';
export function fromPromise<T>(input: PromiseLike<T>, scheduler?: SchedulerLike) {
if (!scheduler) {
return new Observable<T>(subscribeToPromise(input));
} else {
return schedulePromise(input, scheduler);
}
}

379
node_modules/rxjs/src/internal/observable/generate.ts generated vendored Normal file
View File

@ -0,0 +1,379 @@
import { Observable } from '../Observable';
import { Subscriber } from '../Subscriber';
import { identity } from '../util/identity';
import { SchedulerAction, SchedulerLike } from '../types';
import { isScheduler } from '../util/isScheduler';
export type ConditionFunc<S> = (state: S) => boolean;
export type IterateFunc<S> = (state: S) => S;
export type ResultFunc<S, T> = (state: S) => T;
interface SchedulerState<T, S> {
needIterate?: boolean;
state: S;
subscriber: Subscriber<T>;
condition?: ConditionFunc<S>;
iterate: IterateFunc<S>;
resultSelector: ResultFunc<S, T>;
}
export interface GenerateBaseOptions<S> {
/**
* Initial state.
*/
initialState: S;
/**
* Condition function that accepts state and returns boolean.
* When it returns false, the generator stops.
* If not specified, a generator never stops.
*/
condition?: ConditionFunc<S>;
/**
* Iterate function that accepts state and returns new state.
*/
iterate: IterateFunc<S>;
/**
* SchedulerLike to use for generation process.
* By default, a generator starts immediately.
*/
scheduler?: SchedulerLike;
}
export interface GenerateOptions<T, S> extends GenerateBaseOptions<S> {
/**
* Result selection function that accepts state and returns a value to emit.
*/
resultSelector: ResultFunc<S, T>;
}
/**
* Generates an observable sequence by running a state-driven loop
* producing the sequence's elements, using the specified scheduler
* to send out observer messages.
*
* ![](generate.png)
*
* @example <caption>Produces sequence of 0, 1, 2, ... 9, then completes.</caption>
* const res = generate(0, x => x < 10, x => x + 1, x => x);
*
* @example <caption>Using asap scheduler, produces sequence of 2, 3, 5, then completes.</caption>
* const res = generate(1, x => x < 5, x => x * 2, x => x + 1, asap);
*
* @see {@link from}
* @see {@link Observable}
*
* @param {S} initialState Initial state.
* @param {function (state: S): boolean} condition Condition to terminate generation (upon returning false).
* @param {function (state: S): S} iterate Iteration step function.
* @param {function (state: S): T} resultSelector Selector function for results produced in the sequence. (deprecated)
* @param {SchedulerLike} [scheduler] A {@link SchedulerLike} on which to run the generator loop. If not provided, defaults to emit immediately.
* @returns {Observable<T>} The generated sequence.
*/
export function generate<T, S>(initialState: S,
condition: ConditionFunc<S>,
iterate: IterateFunc<S>,
resultSelector: ResultFunc<S, T>,
scheduler?: SchedulerLike): Observable<T>;
/**
* Generates an Observable by running a state-driven loop
* that emits an element on each iteration.
*
* <span class="informal">Use it instead of nexting values in a for loop.</span>
*
* <img src="./img/generate.png" width="100%">
*
* `generate` allows you to create stream of values generated with a loop very similar to
* traditional for loop. First argument of `generate` is a beginning value. Second argument
* is a function that accepts this value and tests if some condition still holds. If it does,
* loop continues, if not, it stops. Third value is a function which takes previously defined
* value and modifies it in some way on each iteration. Note how these three parameters
* are direct equivalents of three expressions in regular for loop: first expression
* initializes some state (for example numeric index), second tests if loop can make next
* iteration (for example if index is lower than 10) and third states how defined value
* will be modified on every step (index will be incremented by one).
*
* Return value of a `generate` operator is an Observable that on each loop iteration
* emits a value. First, condition function is ran. If it returned true, Observable
* emits currently stored value (initial value at the first iteration) and then updates
* that value with iterate function. If at some point condition returned false, Observable
* completes at that moment.
*
* Optionally you can pass fourth parameter to `generate` - a result selector function which allows you
* to immediately map value that would normally be emitted by an Observable.
*
* If you find three anonymous functions in `generate` call hard to read, you can provide
* single object to the operator instead. That object has properties: `initialState`,
* `condition`, `iterate` and `resultSelector`, which should have respective values that you
* would normally pass to `generate`. `resultSelector` is still optional, but that form
* of calling `generate` allows you to omit `condition` as well. If you omit it, that means
* condition always holds, so output Observable will never complete.
*
* Both forms of `generate` can optionally accept a scheduler. In case of multi-parameter call,
* scheduler simply comes as a last argument (no matter if there is resultSelector
* function or not). In case of single-parameter call, you can provide it as a
* `scheduler` property on object passed to the operator. In both cases scheduler decides when
* next iteration of the loop will happen and therefore when next value will be emitted
* by the Observable. For example to ensure that each value is pushed to the observer
* on separate task in event loop, you could use `async` scheduler. Note that
* by default (when no scheduler is passed) values are simply emitted synchronously.
*
*
* @example <caption>Use with condition and iterate functions.</caption>
* const generated = generate(0, x => x < 3, x => x + 1);
*
* generated.subscribe(
* value => console.log(value),
* err => {},
* () => console.log('Yo!')
* );
*
* // Logs:
* // 0
* // 1
* // 2
* // "Yo!"
*
*
* @example <caption>Use with condition, iterate and resultSelector functions.</caption>
* const generated = generate(0, x => x < 3, x => x + 1, x => x * 1000);
*
* generated.subscribe(
* value => console.log(value),
* err => {},
* () => console.log('Yo!')
* );
*
* // Logs:
* // 0
* // 1000
* // 2000
* // "Yo!"
*
*
* @example <caption>Use with options object.</caption>
* const generated = generate({
* initialState: 0,
* condition(value) { return value < 3; },
* iterate(value) { return value + 1; },
* resultSelector(value) { return value * 1000; }
* });
*
* generated.subscribe(
* value => console.log(value),
* err => {},
* () => console.log('Yo!')
* );
*
* // Logs:
* // 0
* // 1000
* // 2000
* // "Yo!"
*
* @example <caption>Use options object without condition function.</caption>
* const generated = generate({
* initialState: 0,
* iterate(value) { return value + 1; },
* resultSelector(value) { return value * 1000; }
* });
*
* generated.subscribe(
* value => console.log(value),
* err => {},
* () => console.log('Yo!') // This will never run.
* );
*
* // Logs:
* // 0
* // 1000
* // 2000
* // 3000
* // ...and never stops.
*
*
* @see {@link from}
* @see {@link index/Observable.create}
*
* @param {S} initialState Initial state.
* @param {function (state: S): boolean} condition Condition to terminate generation (upon returning false).
* @param {function (state: S): S} iterate Iteration step function.
* @param {function (state: S): T} [resultSelector] Selector function for results produced in the sequence.
* @param {Scheduler} [scheduler] A {@link Scheduler} on which to run the generator loop. If not provided, defaults to emitting immediately.
* @return {Observable<T>} The generated sequence.
*/
export function generate<S>(initialState: S,
condition: ConditionFunc<S>,
iterate: IterateFunc<S>,
scheduler?: SchedulerLike): Observable<S>;
/**
* Generates an observable sequence by running a state-driven loop
* producing the sequence's elements, using the specified scheduler
* to send out observer messages.
* The overload accepts options object that might contain initial state, iterate,
* condition and scheduler.
*
* ![](generate.png)
*
* @example <caption>Produces sequence of 0, 1, 2, ... 9, then completes.</caption>
* const res = generate({
* initialState: 0,
* condition: x => x < 10,
* iterate: x => x + 1,
* });
*
* @see {@link from}
* @see {@link Observable}
*
* @param {GenerateBaseOptions<S>} options Object that must contain initialState, iterate and might contain condition and scheduler.
* @returns {Observable<S>} The generated sequence.
*/
export function generate<S>(options: GenerateBaseOptions<S>): Observable<S>;
/**
* Generates an observable sequence by running a state-driven loop
* producing the sequence's elements, using the specified scheduler
* to send out observer messages.
* The overload accepts options object that might contain initial state, iterate,
* condition, result selector and scheduler.
*
* ![](generate.png)
*
* @example <caption>Produces sequence of 0, 1, 2, ... 9, then completes.</caption>
* const res = generate({
* initialState: 0,
* condition: x => x < 10,
* iterate: x => x + 1,
* resultSelector: x => x,
* });
*
* @see {@link from}
* @see {@link Observable}
*
* @param {GenerateOptions<T, S>} options Object that must contain initialState, iterate, resultSelector and might contain condition and scheduler.
* @returns {Observable<T>} The generated sequence.
*/
export function generate<T, S>(options: GenerateOptions<T, S>): Observable<T>;
export function generate<T, S>(initialStateOrOptions: S | GenerateOptions<T, S>,
condition?: ConditionFunc<S>,
iterate?: IterateFunc<S>,
resultSelectorOrObservable?: (ResultFunc<S, T>) | SchedulerLike,
scheduler?: SchedulerLike): Observable<T> {
let resultSelector: ResultFunc<S, T>;
let initialState: S;
if (arguments.length == 1) {
const options = initialStateOrOptions as GenerateOptions<T, S>;
initialState = options.initialState;
condition = options.condition;
iterate = options.iterate;
resultSelector = options.resultSelector || identity as ResultFunc<S, T>;
scheduler = options.scheduler;
} else if (resultSelectorOrObservable === undefined || isScheduler(resultSelectorOrObservable)) {
initialState = initialStateOrOptions as S;
resultSelector = identity as ResultFunc<S, T>;
scheduler = resultSelectorOrObservable as SchedulerLike;
} else {
initialState = initialStateOrOptions as S;
resultSelector = resultSelectorOrObservable as ResultFunc<S, T>;
}
return new Observable<T>(subscriber => {
let state = initialState;
if (scheduler) {
return scheduler.schedule<SchedulerState<T, S>>(dispatch, 0, {
subscriber,
iterate,
condition,
resultSelector,
state
});
}
do {
if (condition) {
let conditionResult: boolean;
try {
conditionResult = condition(state);
} catch (err) {
subscriber.error(err);
return undefined;
}
if (!conditionResult) {
subscriber.complete();
break;
}
}
let value: T;
try {
value = resultSelector(state);
} catch (err) {
subscriber.error(err);
return undefined;
}
subscriber.next(value);
if (subscriber.closed) {
break;
}
try {
state = iterate(state);
} catch (err) {
subscriber.error(err);
return undefined;
}
} while (true);
return undefined;
});
}
function dispatch<T, S>(this: SchedulerAction<SchedulerState<T, S>>, state: SchedulerState<T, S>) {
const { subscriber, condition } = state;
if (subscriber.closed) {
return undefined;
}
if (state.needIterate) {
try {
state.state = state.iterate(state.state);
} catch (err) {
subscriber.error(err);
return undefined;
}
} else {
state.needIterate = true;
}
if (condition) {
let conditionResult: boolean;
try {
conditionResult = condition(state.state);
} catch (err) {
subscriber.error(err);
return undefined;
}
if (!conditionResult) {
subscriber.complete();
return undefined;
}
if (subscriber.closed) {
return undefined;
}
}
let value: T;
try {
value = state.resultSelector(state.state);
} catch (err) {
subscriber.error(err);
return undefined;
}
if (subscriber.closed) {
return undefined;
}
subscriber.next(value);
if (subscriber.closed) {
return undefined;
}
return this.schedule(state);
}

100
node_modules/rxjs/src/internal/observable/iif.ts generated vendored Normal file
View File

@ -0,0 +1,100 @@
import { Observable } from '../Observable';
import { defer } from './defer';
import { EMPTY } from './empty';
import { SubscribableOrPromise } from '../types';
/**
* Decides at subscription time which Observable will actually be subscribed.
*
* <span class="informal">`If` statement for Observables.</span>
*
* `iif` accepts a condition function and two Observables. When
* an Observable returned by the operator is subscribed, condition function will be called.
* Based on what boolean it returns at that moment, consumer will subscribe either to
* the first Observable (if condition was true) or to the second (if condition was false). Condition
* function may also not return anything - in that case condition will be evaluated as false and
* second Observable will be subscribed.
*
* Note that Observables for both cases (true and false) are optional. If condition points to an Observable that
* was left undefined, resulting stream will simply complete immediately. That allows you to, rather
* than controlling which Observable will be subscribed, decide at runtime if consumer should have access
* to given Observable or not.
*
* If you have more complex logic that requires decision between more than two Observables, {@link defer}
* will probably be a better choice. Actually `iif` can be easily implemented with {@link defer}
* and exists only for convenience and readability reasons.
*
*
* ## Examples
* ### Change at runtime which Observable will be subscribed
* ```ts
* import { iif, of } from 'rxjs';
*
* let subscribeToFirst;
* const firstOrSecond = iif(
* () => subscribeToFirst,
* of('first'),
* of('second'),
* );
*
* subscribeToFirst = true;
* firstOrSecond.subscribe(value => console.log(value));
*
* // Logs:
* // "first"
*
* subscribeToFirst = false;
* firstOrSecond.subscribe(value => console.log(value));
*
* // Logs:
* // "second"
*
* ```
*
* ### Control an access to an Observable
* ```ts
* let accessGranted;
* const observableIfYouHaveAccess = iif(
* () => accessGranted,
* of('It seems you have an access...'), // Note that only one Observable is passed to the operator.
* );
*
* accessGranted = true;
* observableIfYouHaveAccess.subscribe(
* value => console.log(value),
* err => {},
* () => console.log('The end'),
* );
*
* // Logs:
* // "It seems you have an access..."
* // "The end"
*
* accessGranted = false;
* observableIfYouHaveAccess.subscribe(
* value => console.log(value),
* err => {},
* () => console.log('The end'),
* );
*
* // Logs:
* // "The end"
* ```
*
* @see {@link defer}
*
* @param {function(): boolean} condition Condition which Observable should be chosen.
* @param {Observable} [trueObservable] An Observable that will be subscribed if condition is true.
* @param {Observable} [falseObservable] An Observable that will be subscribed if condition is false.
* @return {Observable} Either first or second Observable, depending on condition.
* @static true
* @name iif
* @owner Observable
*/
export function iif<T = never, F = never>(
condition: () => boolean,
trueResult: SubscribableOrPromise<T> = EMPTY,
falseResult: SubscribableOrPromise<F> = EMPTY
): Observable<T|F> {
return defer(() => condition() ? trueResult : falseResult);
}

83
node_modules/rxjs/src/internal/observable/interval.ts generated vendored Normal file
View File

@ -0,0 +1,83 @@
import { Observable } from '../Observable';
import { async } from '../scheduler/async';
import { SchedulerAction, SchedulerLike } from '../types';
import { isNumeric } from '../util/isNumeric';
import { Subscriber } from '../Subscriber';
/**
* Creates an Observable that emits sequential numbers every specified
* interval of time, on a specified {@link SchedulerLike}.
*
* <span class="informal">Emits incremental numbers periodically in time.
* </span>
*
* ![](interval.png)
*
* `interval` returns an Observable that emits an infinite sequence of
* ascending integers, with a constant interval of time of your choosing
* between those emissions. The first emission is not sent immediately, but
* only after the first period has passed. By default, this operator uses the
* `async` {@link SchedulerLike} to provide a notion of time, but you may pass any
* {@link SchedulerLike} to it.
*
* ## Example
* Emits ascending numbers, one every second (1000ms) up to the number 3
* ```ts
* import { interval } from 'rxjs';
* import { take } from 'rxjs/operators';
*
* const numbers = interval(1000);
*
* const takeFourNumbers = numbers.pipe(take(4));
*
* takeFourNumbers.subscribe(x => console.log('Next: ', x));
*
* // Logs:
* // Next: 0
* // Next: 1
* // Next: 2
* // Next: 3
* ```
*
* @see {@link timer}
* @see {@link delay}
*
* @param {number} [period=0] The interval size in milliseconds (by default)
* or the time unit determined by the scheduler's clock.
* @param {SchedulerLike} [scheduler=async] The {@link SchedulerLike} to use for scheduling
* the emission of values, and providing a notion of "time".
* @return {Observable} An Observable that emits a sequential number each time
* interval.
* @static true
* @name interval
* @owner Observable
*/
export function interval(period = 0,
scheduler: SchedulerLike = async): Observable<number> {
if (!isNumeric(period) || period < 0) {
period = 0;
}
if (!scheduler || typeof scheduler.schedule !== 'function') {
scheduler = async;
}
return new Observable<number>(subscriber => {
subscriber.add(
scheduler.schedule(dispatch, period, { subscriber, counter: 0, period })
);
return subscriber;
});
}
function dispatch(this: SchedulerAction<IntervalState>, state: IntervalState) {
const { subscriber, counter, period } = state;
subscriber.next(counter);
this.schedule({ subscriber, counter: counter + 1, period }, period);
}
interface IntervalState {
subscriber: Subscriber<number>;
counter: number;
period: number;
}

140
node_modules/rxjs/src/internal/observable/merge.ts generated vendored Normal file
View File

@ -0,0 +1,140 @@
import { Observable } from '../Observable';
import { ObservableInput, SchedulerLike} from '../types';
import { isScheduler } from '../util/isScheduler';
import { mergeAll } from '../operators/mergeAll';
import { fromArray } from './fromArray';
/* tslint:disable:max-line-length */
/** @deprecated use {@link scheduled} and {@link mergeAll} (e.g. `scheduled([ob1, ob2, ob3], scheduled).pipe(mergeAll())*/
export function merge<T>(v1: ObservableInput<T>, scheduler: SchedulerLike): Observable<T>;
/** @deprecated use {@link scheduled} and {@link mergeAll} (e.g. `scheduled([ob1, ob2, ob3], scheduled).pipe(mergeAll())*/
export function merge<T>(v1: ObservableInput<T>, concurrent: number, scheduler: SchedulerLike): Observable<T>;
/** @deprecated use {@link scheduled} and {@link mergeAll} (e.g. `scheduled([ob1, ob2, ob3], scheduled).pipe(mergeAll())*/
export function merge<T, T2>(v1: ObservableInput<T>, v2: ObservableInput<T2>, scheduler: SchedulerLike): Observable<T | T2>;
/** @deprecated use {@link scheduled} and {@link mergeAll} (e.g. `scheduled([ob1, ob2, ob3], scheduled).pipe(mergeAll())*/
export function merge<T, T2>(v1: ObservableInput<T>, v2: ObservableInput<T2>, concurrent: number, scheduler: SchedulerLike): Observable<T | T2>;
/** @deprecated use {@link scheduled} and {@link mergeAll} (e.g. `scheduled([ob1, ob2, ob3], scheduled).pipe(mergeAll())*/
export function merge<T, T2, T3>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, scheduler: SchedulerLike): Observable<T | T2 | T3>;
/** @deprecated use {@link scheduled} and {@link mergeAll} (e.g. `scheduled([ob1, ob2, ob3], scheduled).pipe(mergeAll())*/
export function merge<T, T2, T3>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, concurrent: number, scheduler: SchedulerLike): Observable<T | T2 | T3>;
/** @deprecated use {@link scheduled} and {@link mergeAll} (e.g. `scheduled([ob1, ob2, ob3], scheduled).pipe(mergeAll())*/
export function merge<T, T2, T3, T4>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, scheduler: SchedulerLike): Observable<T | T2 | T3 | T4>;
/** @deprecated use {@link scheduled} and {@link mergeAll} (e.g. `scheduled([ob1, ob2, ob3], scheduled).pipe(mergeAll())*/
export function merge<T, T2, T3, T4>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, concurrent: number, scheduler: SchedulerLike): Observable<T | T2 | T3 | T4>;
/** @deprecated use {@link scheduled} and {@link mergeAll} (e.g. `scheduled([ob1, ob2, ob3], scheduled).pipe(mergeAll())*/
export function merge<T, T2, T3, T4, T5>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, v5: ObservableInput<T5>, scheduler: SchedulerLike): Observable<T | T2 | T3 | T4 | T5>;
/** @deprecated use {@link scheduled} and {@link mergeAll} (e.g. `scheduled([ob1, ob2, ob3], scheduled).pipe(mergeAll())*/
export function merge<T, T2, T3, T4, T5>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, v5: ObservableInput<T5>, concurrent: number, scheduler: SchedulerLike): Observable<T | T2 | T3 | T4 | T5>;
/** @deprecated use {@link scheduled} and {@link mergeAll} (e.g. `scheduled([ob1, ob2, ob3], scheduled).pipe(mergeAll())*/
export function merge<T, T2, T3, T4, T5, T6>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, v5: ObservableInput<T5>, v6: ObservableInput<T6>, scheduler: SchedulerLike): Observable<T | T2 | T3 | T4 | T5 | T6>;
/** @deprecated use {@link scheduled} and {@link mergeAll} (e.g. `scheduled([ob1, ob2, ob3], scheduled).pipe(mergeAll())*/
export function merge<T, T2, T3, T4, T5, T6>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, v5: ObservableInput<T5>, v6: ObservableInput<T6>, concurrent: number, scheduler: SchedulerLike): Observable<T | T2 | T3 | T4 | T5 | T6>;
export function merge<T>(v1: ObservableInput<T>): Observable<T>;
export function merge<T>(v1: ObservableInput<T>, concurrent?: number): Observable<T>;
export function merge<T, T2>(v1: ObservableInput<T>, v2: ObservableInput<T2>): Observable<T | T2>;
export function merge<T, T2>(v1: ObservableInput<T>, v2: ObservableInput<T2>, concurrent?: number): Observable<T | T2>;
export function merge<T, T2, T3>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>): Observable<T | T2 | T3>;
export function merge<T, T2, T3>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, concurrent?: number): Observable<T | T2 | T3>;
export function merge<T, T2, T3, T4>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>): Observable<T | T2 | T3 | T4>;
export function merge<T, T2, T3, T4>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, concurrent?: number): Observable<T | T2 | T3 | T4>;
export function merge<T, T2, T3, T4, T5>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, v5: ObservableInput<T5>): Observable<T | T2 | T3 | T4 | T5>;
export function merge<T, T2, T3, T4, T5>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, v5: ObservableInput<T5>, concurrent?: number): Observable<T | T2 | T3 | T4 | T5>;
export function merge<T, T2, T3, T4, T5, T6>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, v5: ObservableInput<T5>, v6: ObservableInput<T6>): Observable<T | T2 | T3 | T4 | T5 | T6>;
export function merge<T, T2, T3, T4, T5, T6>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, v5: ObservableInput<T5>, v6: ObservableInput<T6>, concurrent?: number): Observable<T | T2 | T3 | T4 | T5 | T6>;
export function merge<T>(...observables: (ObservableInput<T> | number)[]): Observable<T>;
/** @deprecated use {@link scheduled} and {@link mergeAll} (e.g. `scheduled([ob1, ob2, ob3], scheduled).pipe(mergeAll())*/
export function merge<T>(...observables: (ObservableInput<T> | SchedulerLike | number)[]): Observable<T>;
export function merge<T, R>(...observables: (ObservableInput<any> | number)[]): Observable<R>;
/** @deprecated use {@link scheduled} and {@link mergeAll} (e.g. `scheduled([ob1, ob2, ob3], scheduled).pipe(mergeAll())*/
export function merge<T, R>(...observables: (ObservableInput<any> | SchedulerLike | number)[]): Observable<R>;
/* tslint:enable:max-line-length */
/**
* Creates an output Observable which concurrently emits all values from every
* given input Observable.
*
* <span class="informal">Flattens multiple Observables together by blending
* their values into one Observable.</span>
*
* ![](merge.png)
*
* `merge` subscribes to each given input Observable (as arguments), and simply
* forwards (without doing any transformation) all the values from all the input
* Observables to the output Observable. The output Observable only completes
* once all input Observables have completed. Any error delivered by an input
* Observable will be immediately emitted on the output Observable.
*
* ## Examples
* ### Merge together two Observables: 1s interval and clicks
* ```ts
* import { merge, fromEvent, interval } from 'rxjs';
*
* const clicks = fromEvent(document, 'click');
* const timer = interval(1000);
* const clicksOrTimer = merge(clicks, timer);
* clicksOrTimer.subscribe(x => console.log(x));
*
* // Results in the following:
* // timer will emit ascending values, one every second(1000ms) to console
* // clicks logs MouseEvents to console everytime the "document" is clicked
* // Since the two streams are merged you see these happening
* // as they occur.
* ```
*
* ### Merge together 3 Observables, but only 2 run concurrently
* ```ts
* import { merge, interval } from 'rxjs';
* import { take } from 'rxjs/operators';
*
* const timer1 = interval(1000).pipe(take(10));
* const timer2 = interval(2000).pipe(take(6));
* const timer3 = interval(500).pipe(take(10));
* const concurrent = 2; // the argument
* const merged = merge(timer1, timer2, timer3, concurrent);
* merged.subscribe(x => console.log(x));
*
* // Results in the following:
* // - First timer1 and timer2 will run concurrently
* // - timer1 will emit a value every 1000ms for 10 iterations
* // - timer2 will emit a value every 2000ms for 6 iterations
* // - after timer1 hits it's max iteration, timer2 will
* // continue, and timer3 will start to run concurrently with timer2
* // - when timer2 hits it's max iteration it terminates, and
* // timer3 will continue to emit a value every 500ms until it is complete
* ```
*
* @see {@link mergeAll}
* @see {@link mergeMap}
* @see {@link mergeMapTo}
* @see {@link mergeScan}
*
* @param {...ObservableInput} observables Input Observables to merge together.
* @param {number} [concurrent=Number.POSITIVE_INFINITY] Maximum number of input
* Observables being subscribed to concurrently.
* @param {SchedulerLike} [scheduler=null] The {@link SchedulerLike} to use for managing
* concurrency of input Observables.
* @return {Observable} an Observable that emits items that are the result of
* every input Observable.
* @static true
* @name merge
* @owner Observable
*/
export function merge<T, R>(...observables: Array<ObservableInput<any> | SchedulerLike | number>): Observable<R> {
let concurrent = Number.POSITIVE_INFINITY;
let scheduler: SchedulerLike = null;
let last: any = observables[observables.length - 1];
if (isScheduler(last)) {
scheduler = <SchedulerLike>observables.pop();
if (observables.length > 1 && typeof observables[observables.length - 1] === 'number') {
concurrent = <number>observables.pop();
}
} else if (typeof last === 'number') {
concurrent = <number>observables.pop();
}
if (scheduler === null && observables.length === 1 && observables[0] instanceof Observable) {
return <Observable<R>>observables[0];
}
return mergeAll<R>(concurrent)(fromArray<any>(observables, scheduler));
}

41
node_modules/rxjs/src/internal/observable/never.ts generated vendored Normal file
View File

@ -0,0 +1,41 @@
import { Observable } from '../Observable';
import { noop } from '../util/noop';
/**
* An Observable that emits no items to the Observer and never completes.
*
* ![](never.png)
*
* A simple Observable that emits neither values nor errors nor the completion
* notification. It can be used for testing purposes or for composing with other
* Observables. Please note that by never emitting a complete notification, this
* Observable keeps the subscription from being disposed automatically.
* Subscriptions need to be manually disposed.
*
* ## Example
* ### Emit the number 7, then never emit anything else (not even complete)
* ```ts
* import { NEVER } from 'rxjs';
* import { startWith } from 'rxjs/operators';
*
* function info() {
* console.log('Will not be called');
* }
* const result = NEVER.pipe(startWith(7));
* result.subscribe(x => console.log(x), info, info);
*
* ```
*
* @see {@link Observable}
* @see {@link index/EMPTY}
* @see {@link of}
* @see {@link throwError}
*/
export const NEVER = new Observable<never>(noop);
/**
* @deprecated Deprecated in favor of using {@link NEVER} constant.
*/
export function never () {
return NEVER;
}

110
node_modules/rxjs/src/internal/observable/of.ts generated vendored Normal file
View File

@ -0,0 +1,110 @@
import { SchedulerLike } from '../types';
import { isScheduler } from '../util/isScheduler';
import { fromArray } from './fromArray';
import { Observable } from '../Observable';
import { scheduleArray } from '../scheduled/scheduleArray';
/* tslint:disable:max-line-length */
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
export function of<T>(a: T, scheduler: SchedulerLike): Observable<T>;
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
export function of<T, T2>(a: T, b: T2, scheduler: SchedulerLike): Observable<T | T2>;
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
export function of<T, T2, T3>(a: T, b: T2, c: T3, scheduler: SchedulerLike): Observable<T | T2 | T3>;
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
export function of<T, T2, T3, T4>(a: T, b: T2, c: T3, d: T4, scheduler: SchedulerLike): Observable<T | T2 | T3 | T4>;
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
export function of<T, T2, T3, T4, T5>(a: T, b: T2, c: T3, d: T4, e: T5, scheduler: SchedulerLike): Observable<T | T2 | T3 | T4 | T5>;
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
export function of<T, T2, T3, T4, T5, T6>(a: T, b: T2, c: T3, d: T4, e: T5, f: T6, scheduler: SchedulerLike): Observable<T | T2 | T3 | T4 | T5 | T6>;
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
export function of<T, T2, T3, T4, T5, T6, T7>(a: T, b: T2, c: T3, d: T4, e: T5, f: T6, g: T7, scheduler: SchedulerLike):
Observable<T | T2 | T3 | T4 | T5 | T6 | T7>;
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
export function of<T, T2, T3, T4, T5, T6, T7, T8>(a: T, b: T2, c: T3, d: T4, e: T5, f: T6, g: T7, h: T8, scheduler: SchedulerLike):
Observable<T | T2 | T3 | T4 | T5 | T6 | T7 | T8>;
/** @deprecated use {@link scheduled} instead `scheduled([a, b, c], scheduler)` */
export function of<T, T2, T3, T4, T5, T6, T7, T8, T9>(a: T, b: T2, c: T3, d: T4, e: T5, f: T6, g: T7, h: T8, i: T9, scheduler: SchedulerLike):
Observable<T | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9>;
export function of<T>(...args: (T | SchedulerLike)[]): Observable<T>;
// TODO(benlesh): Update the typings for this when we can switch to TS 3.x
export function of<T>(a: T): Observable<T>;
export function of<T, T2>(a: T, b: T2): Observable<T | T2>;
export function of<T, T2, T3>(a: T, b: T2, c: T3): Observable<T | T2 | T3>;
export function of<T, T2, T3, T4>(a: T, b: T2, c: T3, d: T4): Observable<T | T2 | T3 | T4>;
export function of<T, T2, T3, T4, T5>(a: T, b: T2, c: T3, d: T4, e: T5): Observable<T | T2 | T3 | T4 | T5>;
export function of<T, T2, T3, T4, T5, T6>(a: T, b: T2, c: T3, d: T4, e: T5, f: T6): Observable<T | T2 | T3 | T4 | T5 | T6>;
export function of<T, T2, T3, T4, T5, T6, T7>(a: T, b: T2, c: T3, d: T4, e: T5, f: T6, g: T7):
Observable<T | T2 | T3 | T4 | T5 | T6 | T7>;
export function of<T, T2, T3, T4, T5, T6, T7, T8>(a: T, b: T2, c: T3, d: T4, e: T5, f: T6, g: T7, h: T8):
Observable<T | T2 | T3 | T4 | T5 | T6 | T7 | T8>;
export function of<T, T2, T3, T4, T5, T6, T7, T8, T9>(a: T, b: T2, c: T3, d: T4, e: T5, f: T6, g: T7, h: T8, i: T9):
Observable<T | T2 | T3 | T4 | T5 | T6 | T7 | T8 | T9>;
export function of<T>(...args: T[]): Observable<T>;
/* tslint:enable:max-line-length */
/**
* Converts the arguments to an observable sequence.
*
* <span class="informal">Each argument becomes a `next` notification.</span>
*
* ![](of.png)
*
* Unlike {@link from}, it does not do any flattening and emits each argument in whole
* as a separate `next` notification.
*
* ## Examples
*
* Emit the values `10, 20, 30`
*
* ```ts
* import { of } from 'rxjs';
*
* of(10, 20, 30)
* .subscribe(
* next => console.log('next:', next),
* err => console.log('error:', err),
* () => console.log('the end'),
* );
* // result:
* // 'next: 10'
* // 'next: 20'
* // 'next: 30'
*
* ```
*
* Emit the array `[1,2,3]`
*
* ```ts
* import { of } from 'rxjs';
*
* of([1,2,3])
* .subscribe(
* next => console.log('next:', next),
* err => console.log('error:', err),
* () => console.log('the end'),
* );
* // result:
* // 'next: [1,2,3]'
* ```
*
* @see {@link from}
* @see {@link range}
*
* @param {...T} values A comma separated list of arguments you want to be emitted
* @return {Observable} An Observable that emits the arguments
* described above and then completes.
* @method of
* @owner Observable
*/
export function of<T>(...args: Array<T | SchedulerLike>): Observable<T> {
let scheduler = args[args.length - 1] as SchedulerLike;
if (isScheduler(scheduler)) {
args.pop();
return scheduleArray(args as T[], scheduler);
} else {
return fromArray(args as T[]);
}
}

View File

@ -0,0 +1,102 @@
import { Observable } from '../Observable';
import { ObservableInput } from '../types';
import { from } from './from';
import { isArray } from '../util/isArray';
import { EMPTY } from './empty';
/* tslint:disable:max-line-length */
export function onErrorResumeNext<R>(v: ObservableInput<R>): Observable<R>;
export function onErrorResumeNext<T2, T3, R>(v2: ObservableInput<T2>, v3: ObservableInput<T3>): Observable<R>;
export function onErrorResumeNext<T2, T3, T4, R>(v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>): Observable<R>;
export function onErrorResumeNext<T2, T3, T4, T5, R>(v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, v5: ObservableInput<T5>): Observable<R>;
export function onErrorResumeNext<T2, T3, T4, T5, T6, R>(v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, v5: ObservableInput<T5>, v6: ObservableInput<T6>): Observable<R>;
export function onErrorResumeNext<R>(...observables: Array<ObservableInput<any> | ((...values: Array<any>) => R)>): Observable<R>;
export function onErrorResumeNext<R>(array: ObservableInput<any>[]): Observable<R>;
/* tslint:enable:max-line-length */
/**
* When any of the provided Observable emits an complete or error notification, it immediately subscribes to the next one
* that was passed.
*
* <span class="informal">Execute series of Observables no matter what, even if it means swallowing errors.</span>
*
* ![](onErrorResumeNext.png)
*
* `onErrorResumeNext` Will subscribe to each observable source it is provided, in order.
* If the source it's subscribed to emits an error or completes, it will move to the next source
* without error.
*
* If `onErrorResumeNext` is provided no arguments, or a single, empty array, it will return {@link index/EMPTY}.
*
* `onErrorResumeNext` is basically {@link concat}, only it will continue, even if one of its
* sources emits an error.
*
* Note that there is no way to handle any errors thrown by sources via the result of
* `onErrorResumeNext`. If you want to handle errors thrown in any given source, you can
* always use the {@link catchError} operator on them before passing them into `onErrorResumeNext`.
*
* ## Example
* Subscribe to the next Observable after map fails</caption>
* ```ts
* import { onErrorResumeNext, of } from 'rxjs';
* import { map } from 'rxjs/operators';
*
* onErrorResumeNext(
* of(1, 2, 3, 0).pipe(
* map(x => {
* if (x === 0) throw Error();
* return 10 / x;
* })
* ),
* of(1, 2, 3),
* )
* .subscribe(
* val => console.log(val),
* err => console.log(err), // Will never be called.
* () => console.log('done'),
* );
*
* // Logs:
* // 10
* // 5
* // 3.3333333333333335
* // 1
* // 2
* // 3
* // "done"
* ```
*
* @see {@link concat}
* @see {@link catchError}
*
* @param {...ObservableInput} sources Observables (or anything that *is* observable) passed either directly or as an array.
* @return {Observable} An Observable that concatenates all sources, one after the other,
* ignoring all errors, such that any error causes it to move on to the next source.
*/
export function onErrorResumeNext<T, R>(...sources: Array<ObservableInput<any> |
Array<ObservableInput<any>> |
((...values: Array<any>) => R)>): Observable<R> {
if (sources.length === 0) {
return EMPTY;
}
const [ first, ...remainder ] = sources;
if (sources.length === 1 && isArray(first)) {
return onErrorResumeNext(...first);
}
return new Observable(subscriber => {
const subNext = () => subscriber.add(
onErrorResumeNext(...remainder).subscribe(subscriber)
);
return from(first).subscribe({
next(value) { subscriber.next(value); },
error: subNext,
complete: subNext,
});
});
}

91
node_modules/rxjs/src/internal/observable/pairs.ts generated vendored Normal file
View File

@ -0,0 +1,91 @@
import { Observable } from '../Observable';
import { SchedulerAction, SchedulerLike } from '../types';
import { Subscriber } from '../Subscriber';
import { Subscription } from '../Subscription';
/**
* Convert an object into an Observable of `[key, value]` pairs.
*
* <span class="informal">Turn entries of an object into a stream.</span>
*
* <img src="./img/pairs.png" width="100%">
*
* `pairs` takes an arbitrary object and returns an Observable that emits arrays. Each
* emitted array has exactly two elements - the first is a key from the object
* and the second is a value corresponding to that key. Keys are extracted from
* an object via `Object.keys` function, which means that they will be only
* enumerable keys that are present on an object directly - not ones inherited
* via prototype chain.
*
* By default these arrays are emitted synchronously. To change that you can
* pass a {@link SchedulerLike} as a second argument to `pairs`.
*
* @example <caption>Converts a javascript object to an Observable</caption>
* ```ts
* import { pairs } from 'rxjs';
*
* const obj = {
* foo: 42,
* bar: 56,
* baz: 78
* };
*
* pairs(obj)
* .subscribe(
* value => console.log(value),
* err => {},
* () => console.log('the end!')
* );
*
* // Logs:
* // ["foo", 42],
* // ["bar", 56],
* // ["baz", 78],
* // "the end!"
* ```
*
* @param {Object} obj The object to inspect and turn into an
* Observable sequence.
* @param {Scheduler} [scheduler] An optional IScheduler to schedule
* when resulting Observable will emit values.
* @returns {(Observable<Array<string|T>>)} An observable sequence of
* [key, value] pairs from the object.
*/
export function pairs<T>(obj: Object, scheduler?: SchedulerLike): Observable<[string, T]> {
if (!scheduler) {
return new Observable<[string, T]>(subscriber => {
const keys = Object.keys(obj);
for (let i = 0; i < keys.length && !subscriber.closed; i++) {
const key = keys[i];
if (obj.hasOwnProperty(key)) {
subscriber.next([key, obj[key]]);
}
}
subscriber.complete();
});
} else {
return new Observable<[string, T]>(subscriber => {
const keys = Object.keys(obj);
const subscription = new Subscription();
subscription.add(
scheduler.schedule<{ keys: string[], index: number, subscriber: Subscriber<[string, T]>, subscription: Subscription, obj: Object }>
(dispatch, 0, { keys, index: 0, subscriber, subscription, obj }));
return subscription;
});
}
}
/** @internal */
export function dispatch<T>(this: SchedulerAction<any>,
state: { keys: string[], index: number, subscriber: Subscriber<[string, T]>, subscription: Subscription, obj: Object }) {
const { keys, index, subscriber, subscription, obj } = state;
if (!subscriber.closed) {
if (index < keys.length) {
const key = keys[index];
subscriber.next([key, obj[key]]);
subscription.add(this.schedule({ keys, index: index + 1, subscriber, subscription, obj }));
} else {
subscriber.complete();
}
}
}

67
node_modules/rxjs/src/internal/observable/partition.ts generated vendored Normal file
View File

@ -0,0 +1,67 @@
import { not } from '../util/not';
import { subscribeTo } from '../util/subscribeTo';
import { filter } from '../operators/filter';
import { ObservableInput } from '../types';
import { Observable } from '../Observable';
/**
* Splits the source Observable into two, one with values that satisfy a
* predicate, and another with values that don't satisfy the predicate.
*
* <span class="informal">It's like {@link filter}, but returns two Observables:
* one like the output of {@link filter}, and the other with values that did not
* pass the condition.</span>
*
* ![](partition.png)
*
* `partition` outputs an array with two Observables that partition the values
* from the source Observable through the given `predicate` function. The first
* Observable in that array emits source values for which the predicate argument
* returns true. The second Observable emits source values for which the
* predicate returns false. The first behaves like {@link filter} and the second
* behaves like {@link filter} with the predicate negated.
*
* ## Example
* Partition a set of numbers into odds and evens observables
* ```ts
* import { of, partition } from 'rxjs';
*
* const observableValues = of(1, 2, 3, 4, 5, 6);
* const [evens$, odds$] = partition(observableValues, (value, index) => value % 2 === 0);
*
* odds$.subscribe(x => console.log('odds', x));
* evens$.subscribe(x => console.log('evens', x));
*
* // Logs:
* // odds 1
* // odds 3
* // odds 5
* // evens 2
* // evens 4
* // evens 6
* ```
*
* @see {@link filter}
*
* @param {function(value: T, index: number): boolean} predicate A function that
* evaluates each value emitted by the source Observable. If it returns `true`,
* the value is emitted on the first Observable in the returned array, if
* `false` the value is emitted on the second Observable in the array. The
* `index` parameter is the number `i` for the i-th source emission that has
* happened since the subscription, starting from the number `0`.
* @param {any} [thisArg] An optional argument to determine the value of `this`
* in the `predicate` function.
* @return {[Observable<T>, Observable<T>]} An array with two Observables: one
* with values that passed the predicate, and another with values that did not
* pass the predicate.
*/
export function partition<T>(
source: ObservableInput<T>,
predicate: (value: T, index: number) => boolean,
thisArg?: any
): [Observable<T>, Observable<T>] {
return [
filter(predicate, thisArg)(new Observable<T>(subscribeTo(source))),
filter(not(predicate, thisArg) as any)(new Observable<T>(subscribeTo(source)))
] as [Observable<T>, Observable<T>];
}

140
node_modules/rxjs/src/internal/observable/race.ts generated vendored Normal file
View File

@ -0,0 +1,140 @@
import { Observable } from '../Observable';
import { isArray } from '../util/isArray';
import { fromArray } from './fromArray';
import { Operator } from '../Operator';
import { Subscriber } from '../Subscriber';
import { Subscription } from '../Subscription';
import { TeardownLogic, ObservableInput } from '../types';
import { OuterSubscriber } from '../OuterSubscriber';
import { InnerSubscriber } from '../InnerSubscriber';
import { subscribeToResult } from '../util/subscribeToResult';
// tslint:disable:max-line-length
export function race<A>(arg: [ObservableInput<A>]): Observable<A>;
export function race<A, B>(arg: [ObservableInput<A>, ObservableInput<B>]): Observable<A | B>;
export function race<A, B, C>(arg: [ObservableInput<A>, ObservableInput<B>, ObservableInput<C>]): Observable<A | B | C>;
export function race<A, B, C, D>(arg: [ObservableInput<A>, ObservableInput<B>, ObservableInput<C>, ObservableInput<D>]): Observable<A | B | C | D>;
export function race<A, B, C, D, E>(arg: [ObservableInput<A>, ObservableInput<B>, ObservableInput<C>, ObservableInput<D>, ObservableInput<E>]): Observable<A | B | C | D | E>;
export function race<T>(arg: ObservableInput<T>[]): Observable<T>;
export function race(arg: ObservableInput<any>[]): Observable<{}>;
export function race<A>(a: ObservableInput<A>): Observable<A>;
export function race<A, B>(a: ObservableInput<A>, b: ObservableInput<B>): Observable<A | B>;
export function race<A, B, C>(a: ObservableInput<A>, b: ObservableInput<B>, c: ObservableInput<C>): Observable<A | B | C>;
export function race<A, B, C, D>(a: ObservableInput<A>, b: ObservableInput<B>, c: ObservableInput<C>, d: ObservableInput<D>): Observable<A | B | C | D>;
export function race<A, B, C, D, E>(a: ObservableInput<A>, b: ObservableInput<B>, c: ObservableInput<C>, d: ObservableInput<D>, e: ObservableInput<E>): Observable<A | B | C | D | E>;
// tslint:enable:max-line-length
export function race<T>(observables: ObservableInput<T>[]): Observable<T>;
export function race(observables: ObservableInput<any>[]): Observable<{}>;
export function race<T>(...observables: ObservableInput<T>[]): Observable<T>;
export function race(...observables: ObservableInput<any>[]): Observable<{}>;
/**
* Returns an Observable that mirrors the first source Observable to emit an item.
*
* ## Example
* ### Subscribes to the observable that was the first to start emitting.
*
* ```ts
* import { race, interval } from 'rxjs';
* import { mapTo } from 'rxjs/operators';
*
* const obs1 = interval(1000).pipe(mapTo('fast one'));
* const obs2 = interval(3000).pipe(mapTo('medium one'));
* const obs3 = interval(5000).pipe(mapTo('slow one'));
*
* race(obs3, obs1, obs2)
* .subscribe(
* winner => console.log(winner)
* );
*
* // result:
* // a series of 'fast one'
* ```
*
* @param {...Observables} ...observables sources used to race for which Observable emits first.
* @return {Observable} an Observable that mirrors the output of the first Observable to emit an item.
* @static true
* @name race
* @owner Observable
*/
export function race<T>(...observables: ObservableInput<any>[]): Observable<T> {
// if the only argument is an array, it was most likely called with
// `race([obs1, obs2, ...])`
if (observables.length === 1) {
if (isArray(observables[0])) {
observables = observables[0] as Observable<any>[];
} else {
return observables[0] as Observable<T>;
}
}
return fromArray(observables, undefined).lift(new RaceOperator<T>());
}
export class RaceOperator<T> implements Operator<T, T> {
call(subscriber: Subscriber<T>, source: any): TeardownLogic {
return source.subscribe(new RaceSubscriber(subscriber));
}
}
/**
* We need this JSDoc comment for affecting ESDoc.
* @ignore
* @extends {Ignored}
*/
export class RaceSubscriber<T> extends OuterSubscriber<T, T> {
private hasFirst: boolean = false;
private observables: Observable<any>[] = [];
private subscriptions: Subscription[] = [];
constructor(destination: Subscriber<T>) {
super(destination);
}
protected _next(observable: any): void {
this.observables.push(observable);
}
protected _complete() {
const observables = this.observables;
const len = observables.length;
if (len === 0) {
this.destination.complete();
} else {
for (let i = 0; i < len && !this.hasFirst; i++) {
let observable = observables[i];
let subscription = subscribeToResult(this, observable, observable as any, i);
if (this.subscriptions) {
this.subscriptions.push(subscription);
}
this.add(subscription);
}
this.observables = null;
}
}
notifyNext(outerValue: T, innerValue: T,
outerIndex: number, innerIndex: number,
innerSub: InnerSubscriber<T, T>): void {
if (!this.hasFirst) {
this.hasFirst = true;
for (let i = 0; i < this.subscriptions.length; i++) {
if (i !== outerIndex) {
let subscription = this.subscriptions[i];
subscription.unsubscribe();
this.remove(subscription);
}
}
this.subscriptions = null;
}
this.destination.next(innerValue);
}
}

90
node_modules/rxjs/src/internal/observable/range.ts generated vendored Normal file
View File

@ -0,0 +1,90 @@
import { SchedulerAction, SchedulerLike } from '../types';
import { Observable } from '../Observable';
/**
* Creates an Observable that emits a sequence of numbers within a specified
* range.
*
* <span class="informal">Emits a sequence of numbers in a range.</span>
*
* ![](range.png)
*
* `range` operator emits a range of sequential integers, in order, where you
* select the `start` of the range and its `length`. By default, uses no
* {@link SchedulerLike} and just delivers the notifications synchronously, but may use
* an optional {@link SchedulerLike} to regulate those deliveries.
*
* ## Example
* Emits the numbers 1 to 10</caption>
* ```ts
* import { range } from 'rxjs';
*
* const numbers = range(1, 10);
* numbers.subscribe(x => console.log(x));
* ```
* @see {@link timer}
* @see {@link index/interval}
*
* @param {number} [start=0] The value of the first integer in the sequence.
* @param {number} count The number of sequential integers to generate.
* @param {SchedulerLike} [scheduler] A {@link SchedulerLike} to use for scheduling
* the emissions of the notifications.
* @return {Observable} An Observable of numbers that emits a finite range of
* sequential integers.
* @static true
* @name range
* @owner Observable
*/
export function range(start: number = 0,
count?: number,
scheduler?: SchedulerLike): Observable<number> {
return new Observable<number>(subscriber => {
if (count === undefined) {
count = start;
start = 0;
}
let index = 0;
let current = start;
if (scheduler) {
return scheduler.schedule(dispatch, 0, {
index, count, start, subscriber
});
} else {
do {
if (index++ >= count) {
subscriber.complete();
break;
}
subscriber.next(current++);
if (subscriber.closed) {
break;
}
} while (true);
}
return undefined;
});
}
/** @internal */
export function dispatch(this: SchedulerAction<any>, state: any) {
const { start, index, count, subscriber } = state;
if (index >= count) {
subscriber.complete();
return;
}
subscriber.next(start);
if (subscriber.closed) {
return;
}
state.index = index + 1;
state.start = start + 1;
this.schedule(state);
}

View File

@ -0,0 +1,84 @@
import { Observable } from '../Observable';
import { SchedulerLike } from '../types';
import { Subscriber } from '../Subscriber';
/**
* Creates an Observable that emits no items to the Observer and immediately
* emits an error notification.
*
* <span class="informal">Just emits 'error', and nothing else.
* </span>
*
* ![](throw.png)
*
* This static operator is useful for creating a simple Observable that only
* emits the error notification. It can be used for composing with other
* Observables, such as in a {@link mergeMap}.
*
* ## Examples
* ### Emit the number 7, then emit an error
* ```ts
* import { throwError, concat, of } from 'rxjs';
*
* const result = concat(of(7), throwError(new Error('oops!')));
* result.subscribe(x => console.log(x), e => console.error(e));
*
* // Logs:
* // 7
* // Error: oops!
* ```
*
* ---
*
* ### Map and flatten numbers to the sequence 'a', 'b', 'c', but throw an error for 2
* ```ts
* import { throwError, interval, of } from 'rxjs';
* import { mergeMap } from 'rxjs/operators';
*
* interval(1000).pipe(
* mergeMap(x => x === 2
* ? throwError('Twos are bad')
* : of('a', 'b', 'c')
* ),
* ).subscribe(x => console.log(x), e => console.error(e));
*
* // Logs:
* // a
* // b
* // c
* // a
* // b
* // c
* // Twos are bad
* ```
*
* @see {@link Observable}
* @see {@link empty}
* @see {@link never}
* @see {@link of}
*
* @param {any} error The particular Error to pass to the error notification.
* @param {SchedulerLike} [scheduler] A {@link SchedulerLike} to use for scheduling
* the emission of the error notification.
* @return {Observable} An error Observable: emits only the error notification
* using the given error argument.
* @static true
* @name throwError
* @owner Observable
*/
export function throwError(error: any, scheduler?: SchedulerLike): Observable<never> {
if (!scheduler) {
return new Observable(subscriber => subscriber.error(error));
} else {
return new Observable(subscriber => scheduler.schedule(dispatch, 0, { error, subscriber }));
}
}
interface DispatchArg {
error: any;
subscriber: Subscriber<any>;
}
function dispatch({ error, subscriber }: DispatchArg) {
subscriber.error(error);
}

101
node_modules/rxjs/src/internal/observable/timer.ts generated vendored Normal file
View File

@ -0,0 +1,101 @@
import { Observable } from '../Observable';
import { SchedulerAction, SchedulerLike } from '../types';
import { async } from '../scheduler/async';
import { isNumeric } from '../util/isNumeric';
import { isScheduler } from '../util/isScheduler';
import { Subscriber } from '../Subscriber';
/**
* Creates an Observable that starts emitting after an `dueTime` and
* emits ever increasing numbers after each `period` of time thereafter.
*
* <span class="informal">Its like {@link index/interval}, but you can specify when
* should the emissions start.</span>
*
* ![](timer.png)
*
* `timer` returns an Observable that emits an infinite sequence of ascending
* integers, with a constant interval of time, `period` of your choosing
* between those emissions. The first emission happens after the specified
* `dueTime`. The initial delay may be a `Date`. By default, this
* operator uses the {@link asyncScheduler} {@link SchedulerLike} to provide a notion of time, but you
* may pass any {@link SchedulerLike} to it. If `period` is not specified, the output
* Observable emits only one value, `0`. Otherwise, it emits an infinite
* sequence.
*
* ## Examples
* ### Emits ascending numbers, one every second (1000ms), starting after 3 seconds
* ```ts
* import { timer } from 'rxjs';
*
* const numbers = timer(3000, 1000);
* numbers.subscribe(x => console.log(x));
* ```
*
* ### Emits one number after five seconds
* ```ts
* import { timer } from 'rxjs';
*
* const numbers = timer(5000);
* numbers.subscribe(x => console.log(x));
* ```
* @see {@link index/interval}
* @see {@link delay}
*
* @param {number|Date} [dueTime] The initial delay time specified as a Date object or as an integer denoting
* milliseconds to wait before emitting the first value of 0`.
* @param {number|SchedulerLike} [periodOrScheduler] The period of time between emissions of the
* subsequent numbers.
* @param {SchedulerLike} [scheduler=async] The {@link SchedulerLike} to use for scheduling
* the emission of values, and providing a notion of "time".
* @return {Observable} An Observable that emits a `0` after the
* `dueTime` and ever increasing numbers after each `period` of time
* thereafter.
* @static true
* @name timer
* @owner Observable
*/
export function timer(dueTime: number | Date = 0,
periodOrScheduler?: number | SchedulerLike,
scheduler?: SchedulerLike): Observable<number> {
let period = -1;
if (isNumeric(periodOrScheduler)) {
period = Number(periodOrScheduler) < 1 && 1 || Number(periodOrScheduler);
} else if (isScheduler(periodOrScheduler)) {
scheduler = periodOrScheduler as any;
}
if (!isScheduler(scheduler)) {
scheduler = async;
}
return new Observable(subscriber => {
const due = isNumeric(dueTime)
? (dueTime as number)
: (+dueTime - scheduler.now());
return scheduler.schedule(dispatch, due, {
index: 0, period, subscriber
});
});
}
interface TimerState {
index: number;
period: number;
subscriber: Subscriber<number>;
}
function dispatch(this: SchedulerAction<TimerState>, state: TimerState) {
const { index, period, subscriber } = state;
subscriber.next(index);
if (subscriber.closed) {
return;
} else if (period === -1) {
return subscriber.complete();
}
state.index = index + 1;
this.schedule(state, period);
}

63
node_modules/rxjs/src/internal/observable/using.ts generated vendored Normal file
View File

@ -0,0 +1,63 @@
import { Observable } from '../Observable';
import { Unsubscribable, ObservableInput } from '../types';
import { from } from './from'; // from from from! LAWL
import { EMPTY } from './empty';
/**
* Creates an Observable that uses a resource which will be disposed at the same time as the Observable.
*
* <span class="informal">Use it when you catch yourself cleaning up after an Observable.</span>
*
* `using` is a factory operator, which accepts two functions. First function returns a disposable resource.
* It can be an arbitrary object that implements `unsubscribe` method. Second function will be injected with
* that object and should return an Observable. That Observable can use resource object during its execution.
* Both functions passed to `using` will be called every time someone subscribes - neither an Observable nor
* resource object will be shared in any way between subscriptions.
*
* When Observable returned by `using` is subscribed, Observable returned from the second function will be subscribed
* as well. All its notifications (nexted values, completion and error events) will be emitted unchanged by the output
* Observable. If however someone unsubscribes from the Observable or source Observable completes or errors by itself,
* the `unsubscribe` method on resource object will be called. This can be used to do any necessary clean up, which
* otherwise would have to be handled by hand. Note that complete or error notifications are not emitted when someone
* cancels subscription to an Observable via `unsubscribe`, so `using` can be used as a hook, allowing you to make
* sure that all resources which need to exist during an Observable execution will be disposed at appropriate time.
*
* @see {@link defer}
*
* @param {function(): ISubscription} resourceFactory A function which creates any resource object
* that implements `unsubscribe` method.
* @param {function(resource: ISubscription): Observable<T>} observableFactory A function which
* creates an Observable, that can use injected resource object.
* @return {Observable<T>} An Observable that behaves the same as Observable returned by `observableFactory`, but
* which - when completed, errored or unsubscribed - will also call `unsubscribe` on created resource object.
*/
export function using<T>(resourceFactory: () => Unsubscribable | void,
observableFactory: (resource: Unsubscribable | void) => ObservableInput<T> | void): Observable<T> {
return new Observable<T>(subscriber => {
let resource: Unsubscribable | void;
try {
resource = resourceFactory();
} catch (err) {
subscriber.error(err);
return undefined;
}
let result: ObservableInput<T> | void;
try {
result = observableFactory(resource);
} catch (err) {
subscriber.error(err);
return undefined;
}
const source = result ? from(result) : EMPTY;
const subscription = source.subscribe(subscriber);
return () => {
subscription.unsubscribe();
if (resource) {
resource.unsubscribe();
}
};
});
}

330
node_modules/rxjs/src/internal/observable/zip.ts generated vendored Normal file
View File

@ -0,0 +1,330 @@
import { Observable } from '../Observable';
import { fromArray } from './fromArray';
import { isArray } from '../util/isArray';
import { Operator } from '../Operator';
import { ObservableInput, PartialObserver, ObservedValueOf } from '../types';
import { Subscriber } from '../Subscriber';
import { Subscription } from '../Subscription';
import { OuterSubscriber } from '../OuterSubscriber';
import { InnerSubscriber } from '../InnerSubscriber';
import { subscribeToResult } from '../util/subscribeToResult';
import { iterator as Symbol_iterator } from '../../internal/symbol/iterator';
/* tslint:disable:max-line-length */
/** @deprecated resultSelector is no longer supported, pipe to map instead */
export function zip<O1 extends ObservableInput<any>, R>(v1: O1, resultSelector: (v1: ObservedValueOf<O1>) => R): Observable<R>;
/** @deprecated resultSelector is no longer supported, pipe to map instead */
export function zip<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, R>(v1: O1, v2: O2, resultSelector: (v1: ObservedValueOf<O1>, v2: ObservedValueOf<O2>) => R): Observable<R>;
/** @deprecated resultSelector is no longer supported, pipe to map instead */
export function zip<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, R>(v1: O1, v2: O2, v3: O3, resultSelector: (v1: ObservedValueOf<O1>, v2: ObservedValueOf<O2>, v3: ObservedValueOf<O3>) => R): Observable<R>;
/** @deprecated resultSelector is no longer supported, pipe to map instead */
export function zip<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, R>(v1: O1, v2: O2, v3: O3, v4: O4, resultSelector: (v1: ObservedValueOf<O1>, v2: ObservedValueOf<O2>, v3: ObservedValueOf<O3>, v4: ObservedValueOf<O4>) => R): Observable<R>;
/** @deprecated resultSelector is no longer supported, pipe to map instead */
export function zip<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>, R>(v1: O1, v2: O2, v3: O3, v4: O4, v5: O5, resultSelector: (v1: ObservedValueOf<O1>, v2: ObservedValueOf<O2>, v3: ObservedValueOf<O3>, v4: ObservedValueOf<O4>, v5: ObservedValueOf<O5>) => R): Observable<R>;
/** @deprecated resultSelector is no longer supported, pipe to map instead */
export function zip<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>, O6 extends ObservableInput<any>, R>(v1: O1, v2: O2, v3: O3, v4: O4, v5: O5, v6: O6, resultSelector: (v1: ObservedValueOf<O1>, v2: ObservedValueOf<O2>, v3: ObservedValueOf<O3>, v4: ObservedValueOf<O4>, v5: ObservedValueOf<O5>, v6: ObservedValueOf<O6>) => R): Observable<R>;
export function zip<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>>(v1: O1, v2: O2): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>]>;
export function zip<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>>(v1: O1, v2: O2, v3: O3): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>, ObservedValueOf<O3>]>;
export function zip<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>>(v1: O1, v2: O2, v3: O3, v4: O4): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>, ObservedValueOf<O3>, ObservedValueOf<O4>]>;
export function zip<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>>(v1: O1, v2: O2, v3: O3, v4: O4, v5: O5): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>, ObservedValueOf<O3>, ObservedValueOf<O4>, ObservedValueOf<O5>]>;
export function zip<O1 extends ObservableInput<any>, O2 extends ObservableInput<any>, O3 extends ObservableInput<any>, O4 extends ObservableInput<any>, O5 extends ObservableInput<any>, O6 extends ObservableInput<any>>(v1: O1, v2: O2, v3: O3, v4: O4, v5: O5, v6: O6): Observable<[ObservedValueOf<O1>, ObservedValueOf<O2>, ObservedValueOf<O3>, ObservedValueOf<O4>, ObservedValueOf<O5>, ObservedValueOf<O6>]>;
export function zip<O extends ObservableInput<any>>(array: O[]): Observable<ObservedValueOf<O>[]>;
export function zip<R>(array: ObservableInput<any>[]): Observable<R>;
/** @deprecated resultSelector is no longer supported, pipe to map instead */
export function zip<O extends ObservableInput<any>, R>(array: O[], resultSelector: (...values: ObservedValueOf<O>[]) => R): Observable<R>;
/** @deprecated resultSelector is no longer supported, pipe to map instead */
export function zip<R>(array: ObservableInput<any>[], resultSelector: (...values: any[]) => R): Observable<R>;
export function zip<O extends ObservableInput<any>>(...observables: O[]): Observable<ObservedValueOf<O>[]>;
export function zip<O extends ObservableInput<any>, R>(...observables: Array<O | ((...values: ObservedValueOf<O>[]) => R)>): Observable<R>;
export function zip<R>(...observables: Array<ObservableInput<any> | ((...values: Array<any>) => R)>): Observable<R>;
/* tslint:enable:max-line-length */
/**
* Combines multiple Observables to create an Observable whose values are calculated from the values, in order, of each
* of its input Observables.
*
* If the last parameter is a function, this function is used to compute the created value from the input values.
* Otherwise, an array of the input values is returned.
*
* ## Example
* Combine age and name from different sources
* ```ts
* import { zip, of } from 'rxjs';
* import { map } from 'rxjs/operators';
*
* let age$ = of<number>(27, 25, 29);
* let name$ = of<string>('Foo', 'Bar', 'Beer');
* let isDev$ = of<boolean>(true, true, false);
*
* zip(age$, name$, isDev$).pipe(
* map(([age, name, isDev]) => ({ age, name, isDev })),
* )
* .subscribe(x => console.log(x));
*
* // outputs
* // { age: 27, name: 'Foo', isDev: true }
* // { age: 25, name: 'Bar', isDev: true }
* // { age: 29, name: 'Beer', isDev: false }
* ```
* @param observables
* @return {Observable<R>}
* @static true
* @name zip
* @owner Observable
*/
export function zip<O extends ObservableInput<any>, R>(
...observables: Array<O | ((...values: ObservedValueOf<O>[]) => R)>
): Observable<ObservedValueOf<O>[]|R> {
const resultSelector = <((...ys: Array<any>) => R)> observables[observables.length - 1];
if (typeof resultSelector === 'function') {
observables.pop();
}
return fromArray(observables, undefined).lift(new ZipOperator(resultSelector));
}
export class ZipOperator<T, R> implements Operator<T, R> {
resultSelector: (...values: Array<any>) => R;
constructor(resultSelector?: (...values: Array<any>) => R) {
this.resultSelector = resultSelector;
}
call(subscriber: Subscriber<R>, source: any): any {
return source.subscribe(new ZipSubscriber(subscriber, this.resultSelector));
}
}
/**
* We need this JSDoc comment for affecting ESDoc.
* @ignore
* @extends {Ignored}
*/
export class ZipSubscriber<T, R> extends Subscriber<T> {
private values: any;
private resultSelector: (...values: Array<any>) => R;
private iterators: LookAheadIterator<any>[] = [];
private active = 0;
constructor(destination: Subscriber<R>,
resultSelector?: (...values: Array<any>) => R,
values: any = Object.create(null)) {
super(destination);
this.resultSelector = (typeof resultSelector === 'function') ? resultSelector : null;
this.values = values;
}
protected _next(value: any) {
const iterators = this.iterators;
if (isArray(value)) {
iterators.push(new StaticArrayIterator(value));
} else if (typeof value[Symbol_iterator] === 'function') {
iterators.push(new StaticIterator(value[Symbol_iterator]()));
} else {
iterators.push(new ZipBufferIterator(this.destination, this, value));
}
}
protected _complete() {
const iterators = this.iterators;
const len = iterators.length;
this.unsubscribe();
if (len === 0) {
this.destination.complete();
return;
}
this.active = len;
for (let i = 0; i < len; i++) {
let iterator: ZipBufferIterator<any, any> = <any>iterators[i];
if (iterator.stillUnsubscribed) {
const destination = this.destination as Subscription;
destination.add(iterator.subscribe(iterator, i));
} else {
this.active--; // not an observable
}
}
}
notifyInactive() {
this.active--;
if (this.active === 0) {
this.destination.complete();
}
}
checkIterators() {
const iterators = this.iterators;
const len = iterators.length;
const destination = this.destination;
// abort if not all of them have values
for (let i = 0; i < len; i++) {
let iterator = iterators[i];
if (typeof iterator.hasValue === 'function' && !iterator.hasValue()) {
return;
}
}
let shouldComplete = false;
const args: any[] = [];
for (let i = 0; i < len; i++) {
let iterator = iterators[i];
let result = iterator.next();
// check to see if it's completed now that you've gotten
// the next value.
if (iterator.hasCompleted()) {
shouldComplete = true;
}
if (result.done) {
destination.complete();
return;
}
args.push(result.value);
}
if (this.resultSelector) {
this._tryresultSelector(args);
} else {
destination.next(args);
}
if (shouldComplete) {
destination.complete();
}
}
protected _tryresultSelector(args: any[]) {
let result: any;
try {
result = this.resultSelector.apply(this, args);
} catch (err) {
this.destination.error(err);
return;
}
this.destination.next(result);
}
}
interface LookAheadIterator<T> extends Iterator<T> {
hasValue(): boolean;
hasCompleted(): boolean;
}
class StaticIterator<T> implements LookAheadIterator<T> {
private nextResult: IteratorResult<T>;
constructor(private iterator: Iterator<T>) {
this.nextResult = iterator.next();
}
hasValue() {
return true;
}
next(): IteratorResult<T> {
const result = this.nextResult;
this.nextResult = this.iterator.next();
return result;
}
hasCompleted() {
const nextResult = this.nextResult;
return nextResult && nextResult.done;
}
}
class StaticArrayIterator<T> implements LookAheadIterator<T> {
private index = 0;
private length = 0;
constructor(private array: T[]) {
this.length = array.length;
}
[Symbol_iterator]() {
return this;
}
next(value?: any): IteratorResult<T> {
const i = this.index++;
const array = this.array;
return i < this.length ? { value: array[i], done: false } : { value: null, done: true };
}
hasValue() {
return this.array.length > this.index;
}
hasCompleted() {
return this.array.length === this.index;
}
}
/**
* We need this JSDoc comment for affecting ESDoc.
* @ignore
* @extends {Ignored}
*/
class ZipBufferIterator<T, R> extends OuterSubscriber<T, R> implements LookAheadIterator<T> {
stillUnsubscribed = true;
buffer: T[] = [];
isComplete = false;
constructor(destination: PartialObserver<T>,
private parent: ZipSubscriber<T, R>,
private observable: Observable<T>) {
super(destination);
}
[Symbol_iterator]() {
return this;
}
// NOTE: there is actually a name collision here with Subscriber.next and Iterator.next
// this is legit because `next()` will never be called by a subscription in this case.
next(): IteratorResult<T> {
const buffer = this.buffer;
if (buffer.length === 0 && this.isComplete) {
return { value: null, done: true };
} else {
return { value: buffer.shift(), done: false };
}
}
hasValue() {
return this.buffer.length > 0;
}
hasCompleted() {
return this.buffer.length === 0 && this.isComplete;
}
notifyComplete() {
if (this.buffer.length > 0) {
this.isComplete = true;
this.parent.notifyInactive();
} else {
this.destination.complete();
}
}
notifyNext(outerValue: T, innerValue: any,
outerIndex: number, innerIndex: number,
innerSub: InnerSubscriber<T, R>): void {
this.buffer.push(innerValue);
this.parent.checkIterators();
}
subscribe(value: any, index: number) {
return subscribeToResult<any, any>(this, this.observable, this, index);
}
}