From 0e99b6e725ae0faec1c6f1b6b750efd27f17d495 Mon Sep 17 00:00:00 2001 From: Ben Lesh Date: Wed, 7 Mar 2018 13:55:41 -0800 Subject: [PATCH] refactor(config): Move config to a module Moves Rx.config to a module so it can be used via any module system as well --- spec/Observable-spec.ts | 5 +-- spec/operators/toPromise-spec.ts | 11 ++---- src/internal/Observable.ts | 57 ++++++++++++++++---------------- src/internal/Rx.ts | 2 ++ src/internal/config.ts | 11 ++++++ 5 files changed, 45 insertions(+), 41 deletions(-) create mode 100644 src/internal/config.ts diff --git a/spec/Observable-spec.ts b/spec/Observable-spec.ts index 599fcc7fb6..b15e8b1002 100644 --- a/spec/Observable-spec.ts +++ b/spec/Observable-spec.ts @@ -74,9 +74,7 @@ describe('Observable', () => { it('should allow Promise to be globally configured', (done) => { let wasCalled = false; - __root__.Rx = {}; - __root__.Rx.config = {}; - __root__.Rx.config.Promise = function MyPromise(callback: any) { + Rx.config.Promise = function MyPromise(callback: any) { wasCalled = true; return new Promise(callback); }; @@ -85,7 +83,6 @@ describe('Observable', () => { expect(x).to.equal(42); }).then(() => { expect(wasCalled).to.be.true; - delete __root__.Rx; done(); }); }); diff --git a/spec/operators/toPromise-spec.ts b/spec/operators/toPromise-spec.ts index e5801c3f6b..b61e9698f6 100644 --- a/spec/operators/toPromise-spec.ts +++ b/spec/operators/toPromise-spec.ts @@ -1,7 +1,6 @@ import { expect } from 'chai'; import * as Rx from '../../src/internal/Rx'; -declare const __root__: any; const Observable = Rx.Observable; /** @test {toPromise} */ @@ -24,18 +23,14 @@ describe('Observable.prototype.toPromise', () => { it('should allow for global config via Rx.config.Promise', (done: MochaDone) => { let wasCalled = false; - __root__.Rx = {}; - __root__.Rx.config = {}; - __root__.Rx.config.Promise = function MyPromise(callback) { + Rx.config.Promise = function MyPromise(callback: Function) { wasCalled = true; - return new Promise(callback); - }; + return new Promise(callback as any); + } as any; Observable.of(42).toPromise().then((x: number) => { expect(wasCalled).to.be.true; expect(x).to.equal(42); - - delete __root__.Rx; done(); }); }); diff --git a/src/internal/Observable.ts b/src/internal/Observable.ts index ab5819a246..c31d656160 100644 --- a/src/internal/Observable.ts +++ b/src/internal/Observable.ts @@ -2,12 +2,12 @@ import { Operator } from './Operator'; import { Subscriber } from './Subscriber'; import { Subscription } from './Subscription'; import { TeardownLogic } from './types'; -import { root } from './util/root'; import { toSubscriber } from './util/toSubscriber'; import { iif } from './observable/iif'; import { observable as Symbol_observable } from '../internal/symbol/observable'; import { OperatorFunction, PartialObserver, Subscribable } from '../internal/types'; import { pipeFromArray } from './util/pipe'; +import { config } from './config'; /** * A representation of any set of values over any amount of time. This is the most basic building block @@ -209,24 +209,14 @@ export class Observable implements Subscribable { /** * @method forEach * @param {Function} next a handler for each value emitted by the observable - * @param {PromiseConstructor} [PromiseCtor] a constructor function used to instantiate the Promise + * @param {PromiseConstructor} [promiseCtor] a constructor function used to instantiate the Promise * @return {Promise} a promise that either resolves on observable completion or * rejects with the handled error */ - forEach(next: (value: T) => void, PromiseCtor?: typeof Promise): Promise { - if (!PromiseCtor) { - if (root.Rx && root.Rx.config && root.Rx.config.Promise) { - PromiseCtor = root.Rx.config.Promise; - } else if (root.Promise) { - PromiseCtor = root.Promise; - } - } - - if (!PromiseCtor) { - throw new Error('no Promise impl found'); - } + forEach(next: (value: T) => void, promiseCtor?: PromiseConstructorLike): PromiseLike { + promiseCtor = getPromiseCtor(promiseCtor); - return new PromiseCtor((resolve, reject) => { + return new promiseCtor((resolve, reject) => { // Must be declared in a separate statement to avoid a RefernceError when // accessing subscription below in the closure due to Temporal Dead Zone. let subscription: Subscription; @@ -307,22 +297,31 @@ export class Observable implements Subscribable { toPromise(this: Observable, PromiseCtor: PromiseConstructorLike): Promise; /* tslint:enable:max-line-length */ - toPromise(PromiseCtor?: PromiseConstructorLike) { - if (!PromiseCtor) { - if (root.Rx && root.Rx.config && root.Rx.config.Promise) { - PromiseCtor = root.Rx.config.Promise; - } else if (root.Promise) { - PromiseCtor = root.Promise; - } - } - - if (!PromiseCtor) { - throw new Error('no Promise impl found'); - } + toPromise(promiseCtor?: PromiseConstructorLike): PromiseLike { + promiseCtor = getPromiseCtor(promiseCtor); - return new PromiseCtor((resolve, reject) => { + return new promiseCtor((resolve, reject) => { let value: any; this.subscribe((x: T) => value = x, (err: any) => reject(err), () => resolve(value)); - }) as Promise; + }); } } + +/** + * Decides between a passed promise constructor from consuming code, + * A default configured promise constructor, and the native promise + * constructor and returns it. If nothing can be found, it will throw + * an error. + * @param promiseCtor The optional promise constructor to passed by consuming code + */ +function getPromiseCtor(promiseCtor: PromiseConstructorLike | undefined) { + if (!promiseCtor) { + promiseCtor = config.Promise || Promise; + } + + if (!promiseCtor) { + throw new Error('no Promise impl found'); + } + + return promiseCtor; +} diff --git a/src/internal/Rx.ts b/src/internal/Rx.ts index df75853838..4caa1c9c0c 100644 --- a/src/internal/Rx.ts +++ b/src/internal/Rx.ts @@ -6,6 +6,8 @@ export {Subject, AnonymousSubject} from './Subject'; /* tslint:enable:no-unused-variable */ export {Observable} from './Observable'; +export { config } from './config'; + // statics /* tslint:disable:no-use-before-declare */ import '../add/observable/bindCallback'; diff --git a/src/internal/config.ts b/src/internal/config.ts new file mode 100644 index 0000000000..844ff99b70 --- /dev/null +++ b/src/internal/config.ts @@ -0,0 +1,11 @@ +/** + * The global configuration object for RxJS, used to configure things + * like what Promise contructor should used to create Promises + */ +export const config = { + /** + * The promise constructor used by default for methods such as + * {@link toPromise} and {@link forEach} + */ + Promise +};