Skip to content

Commit

Permalink
feat(toPromise): add higher-order lettable version of toPromise
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonaden committed Sep 8, 2017
1 parent bd7f5ed commit 1627da2
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 17 deletions.
19 changes: 2 additions & 17 deletions src/operator/toPromise.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Observable } from '../Observable';
import { root } from '../util/root';
import { toPromise as higherOrder } from '../operators/toPromise';

/* tslint:disable:max-line-length */
export function toPromise<T>(this: Observable<T>): Promise<T>;
Expand Down Expand Up @@ -56,20 +56,5 @@ export function toPromise<T>(this: Observable<T>, PromiseCtor: typeof Promise):
* @owner Observable
*/
export function toPromise<T>(this: Observable<T>, PromiseCtor?: typeof Promise): Promise<T> {
if (!PromiseCtor) {
if (root.Rx && root.Rx.config && root.Rx.config.Promise) {
PromiseCtor = root.Rx.config.Promise;
} else if (root.Promise) {
PromiseCtor = root.Promise;
}
}

if (!PromiseCtor) {
throw new Error('no Promise impl found');
}

return new PromiseCtor((resolve, reject) => {
let value: any;
this.subscribe((x: T) => value = x, (err: any) => reject(err), () => resolve(value));
});
return higherOrder(PromiseCtor)(this);
}
1 change: 1 addition & 0 deletions src/operators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export { timeout } from './timeout';
export { timeoutWith } from './timeoutWith';
export { timestamp } from './timestamp';
export { toArray } from './toArray';
export { toPromise } from './toPromise';
export { window } from './window';
export { windowCount } from './windowCount';
export { windowTime } from './windowTime';
Expand Down
78 changes: 78 additions & 0 deletions src/operators/toPromise.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { Observable } from '../Observable';
import { root } from '../util/root';
import { UnaryFunction } from '../interfaces';

/* tslint:disable:max-line-length */
export function toPromise<T>(): UnaryFunction<Observable<T>, Promise<T>>;
export function toPromise<T>(PromiseCtor: typeof Promise): UnaryFunction<Observable<T>, Promise<T>>;
/* tslint:enable:max-line-length */

/**
* Converts an Observable sequence to a ES2015 compliant promise.
*
* @example
* // Using normal ES2015
* let source = Rx.Observable
* .of(42)
* .toPromise();
*
* source.then((value) => console.log('Value: %s', value));
* // => Value: 42
*
* // Rejected Promise
* // Using normal ES2015
* let source = Rx.Observable
* .throw(new Error('woops'))
* .toPromise();
*
* source
* .then((value) => console.log('Value: %s', value))
* .catch((err) => console.log('Error: %s', err));
* // => Error: Error: woops
*
* // Setting via the config
* Rx.config.Promise = RSVP.Promise;
*
* let source = Rx.Observable
* .of(42)
* .toPromise();
*
* source.then((value) => console.log('Value: %s', value));
* // => Value: 42
*
* // Setting via the method
* let source = Rx.Observable
* .of(42)
* .toPromise(RSVP.Promise);
*
* source.then((value) => console.log('Value: %s', value));
* // => Value: 42
*
* @param {PromiseConstructor} [PromiseCtor] The constructor of the promise. If not provided,
* it will look for a constructor first in Rx.config.Promise then fall back to
* the native Promise constructor if available.
* @return {Promise<T>} An ES2015 compatible promise with the last value from
* the observable sequence.
* @method toPromise
* @owner Observable
*/
export function toPromise<T>(PromiseCtor?: typeof Promise): UnaryFunction<Observable<T>, Promise<T>> {
return (source: Observable<T>) => {
if (!PromiseCtor) {
if (root.Rx && root.Rx.config && root.Rx.config.Promise) {
PromiseCtor = root.Rx.config.Promise;
} else if (root.Promise) {
PromiseCtor = root.Promise;
}
}

if (!PromiseCtor) {
throw new Error('no Promise impl found');
}

return new PromiseCtor((resolve, reject) => {
let value: any;
source.subscribe((x: T) => value = x, (err: any) => reject(err), () => resolve(value));
});
};
}

0 comments on commit 1627da2

Please sign in to comment.