Coder Social home page Coder Social logo

Option for auto-wrapping exceptions about when HOT 15 CLOSED

cujojs avatar cujojs commented on September 1, 2024
Option for auto-wrapping exceptions

from when.

Comments (15)

briancavalier avatar briancavalier commented on September 1, 2024

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.

oberstet avatar oberstet commented on September 1, 2024

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.

briancavalier avatar briancavalier commented on September 1, 2024

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.

oberstet avatar oberstet commented on September 1, 2024

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.

briancavalier avatar briancavalier commented on September 1, 2024

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.

briancavalier avatar briancavalier commented on September 1, 2024

@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.

oberstet avatar oberstet commented on September 1, 2024

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.

briancavalier avatar briancavalier commented on September 1, 2024

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.

briancavalier avatar briancavalier commented on September 1, 2024

There's related discussion going on over in #18 as well.

from when.

oberstet avatar oberstet commented on September 1, 2024

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.

TobiaszCudnik avatar TobiaszCudnik commented on September 1, 2024

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.

briancavalier avatar briancavalier commented on September 1, 2024

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:

  1. 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).
  2. 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.
  3. It allows when() and all the when.*() 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.

oberstet avatar oberstet commented on September 1, 2024

+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.

briancavalier avatar briancavalier commented on September 1, 2024

Thanks for weighing in, @oberstet. We're considering adding this for when.js 2.0 (which is not far off, btw!)

from when.

briancavalier avatar briancavalier commented on September 1, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.