Comments (15)
Thanks for the more complete explanation of the situation--I think I understand better now what you were asking. It makes sense that exceptions caused by bugs during development should be loud--as opposed to "normal" errors which should be handled by a rejection handler. The problem is, of course, how to distinguish between the two.
The upcoming when.js v1.1 release (very soon) will have an experimental debug module that will log some information about promise rejections in promises created using when.js (via when.defer()), and promises consumed by when.js (e.g. if there are multiple promise implementations in play in your system, such as $.Deferred, dojo.Deferred, Q, etc.)
I say "experimental" because we're still playing with what information is most useful to log, and when to log it. In this first release, we went for a minimalist approach to avoid being yet another debug firehose.
If you'd like to try it out now, you can grab the dev branch, and load when/debug
instead of when
. We'd certainly love to hear what you think of this overall approach to providing debug support, and any specific feedback you have on what information is logged at what times.
from when.
Thanks for pointing to dev branch .. I'll try it. Few comments already:
For now, we worked around the "issue" by making deferred class used by AutobahnJS pluggable. For dev, we now (again) use jQuery deferreds.
Mixed deferreds: yeah, could be an issue (we dont do it). If so, would be probably helpful to warn about such use in dev mode (i.e. when I to when.all() with an array of alien deferreds or even mixed.
Regarding "what to log": I'd prefer to simply not catch any exceptions thrown in resolve handlers when debug option is set. Because then I can just click the exception / dive into code using browser debugger, without any additional logging code "in the way".
Do you make a wrapped exception forward to reject handler an instance of some specific class, so that it is easy to differentiate in reject handler between those and stuff "normally" provided via explicit reject() call?
How do you (plan to) handle exceptions thrown from reject handlers?
from when.
Appreciate the quick feedback @oberstet! We'll look into ways we might allow exceptions to propagate up to the host environment (so that the trigger the host's stack trace logging facilities) in debug mode, while still maintaining Promises/A.
We don't wrap the exceptions in any special type. I suppose we could (Crockford) beget from them, but I'd really want them to be usable as the original exception, rather than having to do something like rejectedError.getRealError()
. We'll give this one some thought, too.
Exceptions thrown by rejection handlers are treated in the same way. You can think of them as "rethrowing" an exception. That is, the next promise in the promise chain will receive that exception as its rejection value.
With regular try/catch
, if you catch an exception, you must rethrow it or it will not propagate. That's great because many times we can just not catch, and allow exceptions to propagate up the stack to a caller who is interested and can handle them.
Rejections in when.js, and Promises/A in general, behave similarly in that if you "catch" an error by registering an error handler with a promise that rejects, you must "rethrow" the error by either actually using throw
(and having it translated into a rejection for you), or by returning another rejected promise (which will be easier in when.js v1.1.0 using when.reject()).
The problem is, as you've seen, host environments have no way of knowing when a rejected promise has "reached the top of the stack", in the same way they do exceptions. We're hoping this is where when/debug
will be useful, once we go through a couple iterations with it.
from when.
I am not sure if I get this: an exception thrown in resolve handler of level1 is given to reject handler of level1?
You might want to rethink that. Have a look at what Twisted does:
http://twistedmatrix.com/documents/current/core/howto/defer.html#auto3
http://twistedmatrix.com/documents/current/core/img/deferred-process.png
An exception in resolve level1 is handled by reject in level2.
This way, resolve/reject handler do not get called with args from different levels. No ambiguity.
Also, if a reject handler level1 returns successfully, it'll get handled in resolve of level2. etc etc
This is a sane design, and more important: it has been contested in practice for years.
If you mix up levels, you put the burden of differentiating from which level (same or previous) onto developers ..
Note, this is orthogonal to the debug feature: let exceptions propagate to host env.
from when.
Sorry if I confused the issue! I think we're saying the same thing. In Promises/A, that's how forwarding works: an exception thrown in resolver handler of level1 is given to the rejection handler of level2. Similarly for resolutions.
from when.
@oberstet Here's a quick fiddle, showing how Promises/A behaves very similarly to Twisted Deferred. There are some differences, such as Twisted Deferreds being mutable, and Promises being immutable, but in practice they behave very similarly, and the concepts are the same.
The immutability, imho, is an advantage, in that a single promise can be given to multiple consumers, and they will all observe the same result, even if the consumers interleave and register new promise callbacks.
from when.
Interesting. Those examples might even make sense to add to docs. Mutability: tend to agree. Have been thinking a bit about development option: in dev. mode, an exception thrown in reject/resolve handlers could be propagated to host env whenever there is no handler registered on subsequent level ..
I will look/try more thoroughly when I'm back (will be away for 3 weeks) ..
from when.
Excellent suggestion on adding that example to the docs. I have a few fiddles that would be good to add, so I created a new issue #32 to remind us to add them to the wiki.
from when.
There's related discussion going on over in #18 as well.
from when.
Hi Chris, thanks! I am on a road trip until 18.5. will answer when back ..mail is kind of unavail / pain on the road
Von Samsung Mobile gesendet
Brian Cavalier [email protected] hat geschrieben:
Excellent suggestion on adding that example to the docs. I have a few fiddles that would be good to add, so I created a new issue #32 to remind us to add them to the wiki.
Reply to this email directly or view it on GitHub:
#28 (comment)
from when.
Wouldn't a global reject handler be a better approach than the separate debug build? In such a handler developer could rethrow an exception or customize it to it's own logger or needs.
I'm facing same situation right now and i need to step using a debugger to catch the exceptions.
from when.
Hey @TobiaszCudnik, the primary use case for promises is dealing with asynchronous operations, where standard exception handling is effectively useless, since they occur in a future turn of the event loop--and hence a different call stack. However, the exception concept is still valid. Promises/A promises provide an async analog to exceptions by translating exceptions into rejections so that they can be observed by calling code which would otherwise not be able to catch the exception.
I also feel that a single, global reject handler callback for all promises isn't a scalable solution for application-level error/rejection handling. I feel that a model more like exceptions, but that works in the face of asynchrony, is a better, more scalable solution. IMHO, that's what promises provide.
That said, I do see potential value in adding a global reject handler callback for when/debug
. Since it would be only for debugging, developers would be less tempted (I hope!) to use it for application error handling.
FWIW, when/debug
does some additional things that are useful for debugging:
- It provides a
toString
for deferreds, promises, and resolvers to make logging more friendly. The toString includes information about the state of the promise (or associated promise in the case of deferreds and resolvers), and the resolution value (if resolved). - It catches exceptions that typically represent coding mistakes, such as SyntaxError, ReferenceError, and the like, and rethrows them in a way that ensures they will propagate up to the host env, generating a loud stack trace.
- It allows
when()
and all thewhen.*()
methods to debug (at least minimally) foreign promises when it assimilates them.
I could see adding the ability to set your own function as, say, when.globalRejectionHandler
, and promises created using when/debug
would call that when they are rejected. Again, only for true debugging, and not as a real application error handling mechanism.
Does that seem reasonable?
from when.
+1 for a user definable global rejection handler for debugging purposes.
Most convenient from my POV would be if that still allowed to get stack traces / developer experience just as uncaught expections in non-asynch code has.
from when.
Thanks for weighing in, @oberstet. We're considering adding this for when.js 2.0 (which is not far off, btw!)
from when.
I believe as of 1.6, everything that was discussed as a potential addition to when/debug in this issue (being loud about obvious errors, like SyntaxError, and a global error handler) has been released. Closing.
Please create a new issue if there are related things you'd like to disucss!
from when.
Related Issues (20)
- JSPM build (SystemJS builder) failing on [email protected] HOT 3
- Does not work in NodeJS (ReactJS Native) HOT 12
- Visual Studio debugger breakes from adding When to WebPack bundle. HOT 13
- 3.7.7 breakes the build on Windows HOT 2
- no such file or directory .... es6-shim/makePromise HOT 2
- Global rejection events completely broken in a bundled environment (eg. Webpack)
- When not working in Jasmine tests
- when.reduce UnhandledPromiseRejectionWarning HOT 4
- Misleading unhandled rejection warning when using when.settle HOT 10
- npm install ! has errors HOT 1
- Usage hello world example fails with TypeError HOT 3
- Binding context to promise chain HOT 2
- Add react-native support HOT 2
- File 404 when try to use in browser environment
- Promise.js first function never runs HOT 2
- RTE TypeError after production build HOT 4
- Does function call also accept promises? HOT 4
- Current project status HOT 1
- npm install failing with 404 error code
- Mark package as deprecated on npm?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from when.