From 86a909c06db409f724198d795130ca0f50a93511 Mon Sep 17 00:00:00 2001 From: Jay Phelps Date: Mon, 5 Dec 2016 15:26:16 -0800 Subject: [PATCH] fix(errors): Better error message when you return non-observable things, (#2152) like `undefined` fixes #215 --- spec/util/subscribeToResult-spec.ts | 24 ++++++++++++++++++++++-- src/util/subscribeToResult.ts | 16 +++++++++------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/spec/util/subscribeToResult-spec.ts b/spec/util/subscribeToResult-spec.ts index 41c1ca3895..6101060b6c 100644 --- a/spec/util/subscribeToResult-spec.ts +++ b/spec/util/subscribeToResult-spec.ts @@ -125,7 +125,8 @@ describe('subscribeToResult', () => { const subscriber = new OuterSubscriber(x => { done(new Error('should not be called')); }, (x) => { - expect(x).to.be.an('error', 'invalid observable'); + expect(x).to.be.an('error'); + expect(x.message).to.be.equal('Provided object does not correctly implement Symbol.observable'); done(); }, () => { done(new Error('should not be called')); @@ -138,7 +139,10 @@ describe('subscribeToResult', () => { const subscriber = new OuterSubscriber(x => { done(new Error('should not be called')); }, (x) => { - expect(x).to.be.an('error', 'unknown type returned'); + expect(x).to.be.an('error'); + const msg = 'You provided an invalid object where a stream was expected.' + + ' You can provide an Observable, Promise, Array, or Iterable.'; + expect(x.message).to.be.equal(msg); done(); }, () => { done(new Error('should not be called')); @@ -146,4 +150,20 @@ describe('subscribeToResult', () => { subscribeToResult(subscriber, {}); }); + + it('should emit an error when trying to subscribe to a non-object', (done: MochaDone) => { + const subscriber = new OuterSubscriber(x => { + done(new Error('should not be called')); + }, (x) => { + expect(x).to.be.an('error'); + const msg = 'You provided \'null\' where a stream was expected.' + + ' You can provide an Observable, Promise, Array, or Iterable.'; + expect(x.message).to.be.equal(msg); + done(); + }, () => { + done(new Error('should not be called')); + }); + + subscribeToResult(subscriber, null); + }); }); \ No newline at end of file diff --git a/src/util/subscribeToResult.ts b/src/util/subscribeToResult.ts index 5f6052c29d..3c603f1d80 100644 --- a/src/util/subscribeToResult.ts +++ b/src/util/subscribeToResult.ts @@ -1,6 +1,7 @@ import { root } from './root'; import { isArray } from './isArray'; import { isPromise } from './isPromise'; +import { isObject } from './isObject'; import { Subscriber } from '../Subscriber'; import { Observable, ObservableInput } from '../Observable'; import { $$iterator } from '../symbol/iterator'; @@ -31,9 +32,7 @@ export function subscribeToResult(outerSubscriber: OuterSubscriber, } else { return result.subscribe(destination); } - } - - if (isArray(result)) { + } else if (isArray(result)) { for (let i = 0, len = result.length; i < len && !destination.closed; i++) { destination.next(result[i]); } @@ -55,7 +54,7 @@ export function subscribeToResult(outerSubscriber: OuterSubscriber, root.setTimeout(() => { throw err; }); }); return destination; - } else if (typeof result[$$iterator] === 'function') { + } else if (result && typeof result[$$iterator] === 'function') { const iterator = result[$$iterator](); do { let item = iterator.next(); @@ -68,15 +67,18 @@ export function subscribeToResult(outerSubscriber: OuterSubscriber, break; } } while (true); - } else if (typeof result[$$observable] === 'function') { + } else if (result && typeof result[$$observable] === 'function') { const obs = result[$$observable](); if (typeof obs.subscribe !== 'function') { - destination.error(new Error('invalid observable')); + destination.error(new TypeError('Provided object does not correctly implement Symbol.observable')); } else { return obs.subscribe(new InnerSubscriber(outerSubscriber, outerValue, outerIndex)); } } else { - destination.error(new TypeError('unknown type returned')); + const value = isObject(result) ? 'an invalid object' : `'${result}'`; + const msg = `You provided ${value} where a stream was expected.` + + ' You can provide an Observable, Promise, Array, or Iterable.'; + destination.error(new TypeError(msg)); } return null; }