Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(errors): Better error message when you return non-observable things, #2152

Merged
merged 1 commit into from
Dec 5, 2016

Conversation

jayphelps
Copy link
Member

item$.mergeMap(() => {})
// You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

item$.mergeMap(() => ({}))
// You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

One thing I thought about doing is having operators (who are the ones who call subscribeToResult) pass in the operator name, so that the error message could also say which operator it thinks it occured in. But, what about operator aliases? i.e. mergeMap/flatMap, etc. And also, this could potentially be more confusing if it's a custom operator that calls other operators inside of it--but perhaps that's rare enough in the wild to discount it.

So for example: You provided 'undefined' to 'mergeMap|flatMap' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

Cc/ @kentcdodds

@jayphelps
Copy link
Member Author

jayphelps commented Nov 23, 2016

If we can be sure that subscribeToResult is only ever used when you return something, I can use that word instead of "provided". It seems Observable.from does not use it


Edit: subscribeToResult is used by MergeAllSubscriber, which is used by Observable.merge(...streams), so using the term "return" could be confusing, instead of "provided" (or similar). Open to suggestions, if anyone has them.

@kentcdodds
Copy link

@jayphelps, you're one of my favorites <3

@jayphelps
Copy link
Member Author

jayphelps commented Nov 23, 2016

@kentcdodds hahaha well, I'm sure the others were gonna jump on this too. I literally already had a branch to change this that's been sitting for several months and your issue reminded me to finish.

This really is an annoyance I've had to deal with helping others on gitter, etc.

@kentcdodds
Copy link

Yeah, one thing that really helped me with beginner questions on angular-formly was validating every API with api-check. Would not recommend using this package anymore, but the concept of validating APIs for development (I was inspired by React) is awesome. I imagine TypeScript/Flow could really help with this :)

@jayphelps
Copy link
Member Author

@kentcdodds Yeah, TS shouldn't let you return non-observable things. We could certainly consider adding more robust error checking wrapped in React-style process.env.node_env checks. Would you volunteer to create the ticket to track and (just maybe) give us some pointers?

@kentcdodds
Copy link

Can definitely create a ticket!

@coveralls
Copy link

coveralls commented Nov 23, 2016

Coverage Status

Coverage increased (+0.001%) to 97.687% when pulling 307b888 on jayphelps:error into f51b8f9 on ReactiveX:master.

@robwormald
Copy link
Contributor

We could certainly consider adding more robust error checking wrapped in React-style process.env.node_env checks

Could we avoid introducing any code like this that's going to require a specific build process? We have a ton of consumers of Rx not using Webpack, so I'd like to avoid penalizing them.

@kentcdodds
Copy link

Yes, that would be best. Optimally we should probably do what React's done by having the minified version exclude this stuff. So people not using a build system should use the minified version, and people using a build system can remove that themselves as part of the build. I wonder if there's a better way...

If I recall correctly, @jmdobry had a lib-name.debug.js file for his js-data library which you were supposed to use in development which had helpful things like this and then in production you'd use (and minify yourself) lib-name.js. Seems legit to me.

@kentcdodds
Copy link

All that said, one of the drawbacks of doing an "opt-in" system for this kind of thing is the people who generally need this kind of help wont know to opt into the help and you lose one of the main benefits of doing something like this in the first place. I think that making an opt-out version which removes this stuff is better.

@kentcdodds
Copy link

In any case, this is something that'll take a bit of effort, but it's well worth it IMO :) </done>

@jayphelps
Copy link
Member Author

@robwormald @kentcdodds agreed. We can continue that discussion in #2153 💃

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.';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be nitpicking, but one could return an Rx.Observable or a "lowercase-o observable" which is any object that implements Symbol.observable. How do we differentiate those two things there? Maybe Observable, Promise, Array, Iterable or object implementing Symbol.observable?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I just punted on Symbol.observable because it felt like one of those "if you know it exists, you know it's supported" things. But I'm cool with adding of an object implementing Symbol.observable

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.';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, can we just use a single template string \like this`` here instead of concatenating two strings together? I feel like the newline in the message is fine.

Copy link
Member Author

@jayphelps jayphelps Nov 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you use template strings, the indention will matter and be wack. I would need to do this:

    const msg = `You provided ${value} where a stream was expected.
You can provide an Observable, Promise, Array, or Iterable.`;
// Notice how this can't be indented, otherwise the indention will also transfer through
// e.g. this:
    const msg = `You provided ${value} where a stream was expected.
      You can provide an Observable, Promise, Array, or Iterable.`;
// would output:
You provided null where a stream was expected.
      You can provide an Observable, Promise, Array, or Iterable.

If you're OK with either of these (or something else), I can change it. lmk. I may have to add an eslint ignore line, dunno.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please no. Please, leave it like it is :)

Copy link
Member

@benlesh benlesh Nov 30, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it can't be indented. It just seems inefficient to allocate two strings, then concatenate them into another string. I'm okay with breaking the line length linting rule here too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then again, check the TypeScript compiled output, maybe if accounts for this and fixes it automagically.

@benlesh
Copy link
Member

benlesh commented Dec 5, 2016

:shipit:

@benlesh
Copy link
Member

benlesh commented Dec 5, 2016

LGTM

@benlesh benlesh merged commit 86a909c into ReactiveX:master Dec 5, 2016
@lock
Copy link

lock bot commented Jun 6, 2018

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Jun 6, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants