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

guidance on what error to specify is used when a promise is rejected #60

Open
jpiesing opened this issue Aug 8, 2019 · 12 comments
Open
Assignees

Comments

@jpiesing
Copy link

jpiesing commented Aug 8, 2019

The document currently says;

4.1.2. Rejection Reasons Should Be Errors

Promise rejection reasons should always be instances of the ECMAScript Error type, just like synchronously-thrown exceptions should always be instances of Error as well.

In particular, for DOM or other web platform specs, this means you should never use DOMError, but instead use DOMException, which per WebIDL extends Error. You can of course also use one of the built-in ECMAScript error types.

Looking at existing web APIs, it seems that the most common error to use is one of the built-in ECMAScript error types (e.g. TypeError). I've seen a few examples of DOMException. I've not (yet) found any APIs which define their own Error classes to use with rejection.

When defining an API, sometimes the existing ECMAScript error types include a good fit ( AbortError, NotSupportedError, InvalidStateError). Sometimes they don't or there's a need to distinguish that a promise was rejected for a specific reason.

Please can be document be revised to give some more guidance on what to do when one of the built-in ECMAScript error types is not right.

@domenic
Copy link
Member

domenic commented Aug 8, 2019

Such situations are not specific to promises, so I'm not sure this document is the best place to give such guidance. They apply for synchronously-thrown exceptions as well.

In general we've found on the web platform that giving detailed error information is not very useful; authors rarely write code that distinguishes between different exceptional error cases. (Different non-exceptional error cases sometimes do get different responses from author code, but in those cases you shouldn't be throwing exceptions/rejecting promises anyway.)

@jpiesing
Copy link
Author

jpiesing commented Aug 8, 2019

Such situations are not specific to promises, so I'm not sure this document is the best place to give such guidance. They apply for synchronously-thrown exceptions as well.

Point taken.

In general we've found on the web platform that giving detailed error information is not very useful; authors rarely write code that distinguishes between different exceptional error cases. (Different non-exceptional error cases sometimes do get different responses from author code, but in those cases you shouldn't be throwing exceptions/rejecting promises anyway.)

Please forgive me if I'm being stupid but ...
If an API uses promises for exceptional error cases, it would seem really strange to revert back to something else for non-exceptional error cases.
This is particularly true for async failure modes after method has returned. As far as I can see, the alternative to using promises in these circumstances for a non-exceptional error case would be to use events. That feels really strange to me.

@domenic
Copy link
Member

domenic commented Aug 8, 2019

You can continue to use promises for asynchronous operations. You should just not signal non-exceptional errors using promise rejections. Instead use different fulfillment values. See https://www.w3.org/2001/tag/doc/promises-guide#rejections-should-be-exceptional

@jpiesing
Copy link
Author

jpiesing commented Aug 8, 2019

You can continue to use promises for asynchronous operations. You should just not signal exceptional errors using promise rejections. Instead use different fulfillment values. See https://www.w3.org/2001/tag/doc/promises-guide#rejections-should-be-exceptional

"Good cases for rejections include:"
"..."
"When it will be impossible to complete the requested task: "

There can be non-exceptional async error cases which mean it's impossible to complete the requested task. If I wasn't trying to use promises, this would be a somethingFailedEvent.

@annevk
Copy link
Member

annevk commented Aug 8, 2019

With promises you resolve with a different value for those cases. Similar to how a function might have different return values. (To be clear, in part this is a judgment call, but if the caller is expected to handle the error in a normal flow it's not a rejection.)

@jpiesing
Copy link
Author

jpiesing commented Aug 8, 2019

clear

Thanks for that.
The use case I'm looking at is a failure of an operation for a transient reason which may not happen in a few minutes time. It's not an error by the caller. It's not something which will never work. The caller would however need to re-try.

@annevk
Copy link
Member

annevk commented Aug 8, 2019

If you'd model this as a function call (that happens to take a few minutes), would you return something like "retry" or would you throw? I'd expect the former to make more sense here. And hence, you wanna resolve with something like "retry".

@jpiesing
Copy link
Author

jpiesing commented Aug 8, 2019

If you'd model this as a function call (that happens to take a few minutes), would you return something like "retry" or would you throw? I'd expect the former to make more sense here. And hence, you wanna resolve with something like "retry".

If I modeled this as a function call that took several 10s of seconds then yes, the function would return "retry" rather than throw an Error / Exception.

@annevk
Copy link
Member

annevk commented Aug 9, 2019

There's your answer. Perhaps we should put that explicitly in the guide. That you should always think of them as regular function calls except that you resolve instead of return values/errors and reject rather than throw exceptions.

@jpiesing
Copy link
Author

jpiesing commented Aug 9, 2019

There's your answer. Perhaps we should put that explicitly in the guide. That you should always think of them as regular function calls except that you resolve instead of return values/errors and reject rather than throw exceptions.

That would make it clearer about how to handle error conditions that would not be serious enough to throw an error / exception in an API where promises were not being used..

@jpiesing
Copy link
Author

jpiesing commented Aug 9, 2019

Also please could you consider adding an example to the guide where a promise is resolved to something other than undefined but still simple - e.g. a constant String.

@plinss plinss added this to the 2020-08-03-week milestone May 4, 2020
@atanassov
Copy link

atanassov commented May 26, 2020

@plinss and myself looked at this issue during May 2020 virtual f2f.

It seems the main question was already answered well by @annevk with this comment.

The next question about when to return with error and when to reject is already captured under Section 4.1.3..

We recommend adding a note before 4.1.3., something like:
"If you would've return an error value in case this was a sync function, then resolve the promise with the error value. If you would normally throw an exception in the same API, the go ahead and Reject the promise instead with the same exception."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants