fix(common): introduce isObservable method (#14067)

Closes #8848

PR Close #14067
This commit is contained in:
Dzmitry Shylovich 2017-01-23 20:48:04 +03:00 committed by Miško Hevery
parent fe441186e7
commit ff290af38c
7 changed files with 51 additions and 6 deletions

View File

@ -8,7 +8,7 @@
import {ChangeDetectorRef, OnDestroy, Pipe, PipeTransform, WrappedValue} from '@angular/core'; import {ChangeDetectorRef, OnDestroy, Pipe, PipeTransform, WrappedValue} from '@angular/core';
import {EventEmitter, Observable} from '../facade/async'; import {EventEmitter, Observable} from '../facade/async';
import {isPromise} from '../private_import_core'; import {isObservable, isPromise} from '../private_import_core';
import {InvalidPipeArgumentError} from './invalid_pipe_argument_error'; import {InvalidPipeArgumentError} from './invalid_pipe_argument_error';
interface SubscriptionStrategy { interface SubscriptionStrategy {
@ -116,7 +116,7 @@ export class AsyncPipe implements OnDestroy, PipeTransform {
return _promiseStrategy; return _promiseStrategy;
} }
if ((<any>obj).subscribe) { if (isObservable(obj)) {
return _observableStrategy; return _observableStrategy;
} }

View File

@ -9,3 +9,4 @@
import {__core_private__ as r} from '@angular/core'; import {__core_private__ as r} from '@angular/core';
export const isPromise: typeof r.isPromise = r.isPromise; export const isPromise: typeof r.isPromise = r.isPromise;
export const isObservable: typeof r.isObservable = r.isObservable;

View File

@ -41,7 +41,7 @@ import * as reflector_reader from './reflection/reflector_reader';
import * as reflection_types from './reflection/types'; import * as reflection_types from './reflection/types';
import * as api from './render/api'; import * as api from './render/api';
import * as decorators from './util/decorators'; import * as decorators from './util/decorators';
import {isPromise} from './util/lang'; import {isObservable, isPromise} from './util/lang';
export const __core_private__: { export const __core_private__: {
isDefaultChangeDetectionStrategy: typeof constants.isDefaultChangeDetectionStrategy, isDefaultChangeDetectionStrategy: typeof constants.isDefaultChangeDetectionStrategy,
@ -107,6 +107,7 @@ export const __core_private__: {
_ComponentStillLoadingError?: ComponentStillLoadingError, _ComponentStillLoadingError?: ComponentStillLoadingError,
ComponentStillLoadingError: typeof ComponentStillLoadingError, ComponentStillLoadingError: typeof ComponentStillLoadingError,
isPromise: typeof isPromise, isPromise: typeof isPromise,
isObservable: typeof isObservable,
AnimationTransition: typeof AnimationTransition AnimationTransition: typeof AnimationTransition
view_utils: typeof view_utils, view_utils: typeof view_utils,
} = { } = {
@ -157,5 +158,6 @@ export const __core_private__: {
FILL_STYLE_FLAG: FILL_STYLE_FLAG_, FILL_STYLE_FLAG: FILL_STYLE_FLAG_,
ComponentStillLoadingError: ComponentStillLoadingError, ComponentStillLoadingError: ComponentStillLoadingError,
isPromise: isPromise, isPromise: isPromise,
isObservable: isObservable,
AnimationTransition: AnimationTransition AnimationTransition: AnimationTransition
}; };

View File

@ -6,6 +6,9 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {Observable} from 'rxjs/Observable';
import {$$observable as symbolObservable} from 'rxjs/symbol/observable';
/** /**
* Determine if the argument is shaped like a Promise * Determine if the argument is shaped like a Promise
*/ */
@ -14,3 +17,10 @@ export function isPromise(obj: any): obj is Promise<any> {
// It's up to the caller to ensure that obj.then conforms to the spec // It's up to the caller to ensure that obj.then conforms to the spec
return !!obj && typeof obj.then === 'function'; return !!obj && typeof obj.then === 'function';
} }
/**
* Determine if the argument is an Observable
*/
export function isObservable(obj: any | Observable<any>): obj is Observable<any> {
return !!(obj && obj[symbolObservable]);
}

View File

@ -5,7 +5,8 @@
* Use of this source code is governed by an MIT-style license that can be * Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {isPromise} from '@angular/core/src/util/lang'; import {isObservable, isPromise} from '@angular/core/src/util/lang';
import {of } from 'rxjs/observable/of';
export function main() { export function main() {
describe('isPromise', () => { describe('isPromise', () => {
@ -25,4 +26,22 @@ export function main() {
expect(isPromise(null)).toEqual(false); expect(isPromise(null)).toEqual(false);
}); });
}); });
describe('isObservable', () => {
it('should be true for an Observable', () => expect(isObservable(of (true))).toEqual(true));
it('should be false if the argument is undefined',
() => expect(isObservable(undefined)).toEqual(false));
it('should be false if the argument is null', () => expect(isObservable(null)).toEqual(false));
it('should be false if the argument is an object',
() => expect(isObservable({})).toEqual(false));
it('should be false if the argument is a function',
() => expect(isObservable(() => {})).toEqual(false));
it('should be false if the argument is the object with subscribe function',
() => expect(isObservable({subscribe: () => {}})).toEqual(false));
});
} }

View File

@ -0,0 +1,12 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {__core_private__ as r} from '@angular/core';
export const isPromise: typeof r.isPromise = r.isPromise;
export const isObservable: typeof r.isObservable = r.isObservable;

View File

@ -16,6 +16,7 @@ import * as l from 'rxjs/operator/last';
import {map} from 'rxjs/operator/map'; import {map} from 'rxjs/operator/map';
import {mergeAll} from 'rxjs/operator/mergeAll'; import {mergeAll} from 'rxjs/operator/mergeAll';
import {isObservable, isPromise} from '../private_import_core';
import {PRIMARY_OUTLET} from '../shared'; import {PRIMARY_OUTLET} from '../shared';
export function shallowEqualArrays(a: any[], b: any[]): boolean { export function shallowEqualArrays(a: any[], b: any[]): boolean {
@ -129,11 +130,11 @@ export function andObservables(observables: Observable<Observable<any>>): Observ
export function wrapIntoObservable<T>(value: T | NgModuleFactory<T>| Promise<T>| Observable<T>): export function wrapIntoObservable<T>(value: T | NgModuleFactory<T>| Promise<T>| Observable<T>):
Observable<T> { Observable<T> {
if (value instanceof Observable) { if (isObservable(value)) {
return value; return value;
} }
if (value instanceof Promise) { if (isPromise(value)) {
return fromPromise(value); return fromPromise(value);
} }