Coder Social home page Coder Social logo

Comments (7)

acdlite avatar acdlite commented on July 28, 2024

Ah, good catch!* This should be an easy fix.

*totally unintended pun, I swear

from flummox.

vesparny avatar vesparny commented on July 28, 2024

:)

from flummox.

acdlite avatar acdlite commented on July 28, 2024

Hmm, well, this works:

return promise
  .then(
    body => {
      setTimeout(() =>
        this._dispatch({
          actionId,
          body,
          async: 'success'
        })
      , 0);
    },
    error => {
      setTimeout(() =>
        this._dispatch({
          actionId,
          error,
          async: 'failure',
        })
      , 0);

      return Promise.reject(error);
    }
  );

but it feels pretty hacky. And it means if you await an async action, the action hasn't dispatched yet. Not good.

The other option is to use a catch handler

return promise
  .then(
    body => {
      this._dispatch({
        actionId,
        body,
        async: 'success'
      });
    },
    error => {
      this._dispatch({
        actionId,
        error,
        async: 'failure',
      });

      return Promise.reject(error);
    }
  )
  .catch(error => setTimeout(() => { throw error }, 0));

but that also feels hacky because 1) promise-based operations aren't supposed to throw errors, and 2) the error is being thrown during a different turn of the event loop from when it actually occurred.

I think a better way to handle this would be to have Flux emit an error event, the same way it emits a dispatch event. How does that sound?

from flummox.

acdlite avatar acdlite commented on July 28, 2024

Released as part of v2.12.0. If you want to "un-swallow" the errors, you can do something like this:

flux.addListener('error', error => setTimeout(() => { throw error }, 0));

I would only do this during development, though, if at all.

from flummox.

vesparny avatar vesparny commented on July 28, 2024

Hey man, sorry about the late response here but I've been busy.

I saw you fix and it works.

But..
Even though I totally agree with you when you say that a promise is not supposed to throw, the reality is that it potentially could.
Since you are calling something external like the Dispatcher#dispatch, I think the best approach would be to surround that call with a try/catch block.
This way we can catch the exception and rethrow it in the next tick.
Doing this seems to be the normal behaviour, I mean that if an error occurs the right thing to do is not hiding it, but make the system aware of it, in a natural way (rethrow). Then the developer will be in charge of handling it.

McFly does something similar.
https://github.com/kenwheeler/mcfly/blob/9a45f3e8095d40685a09594256148d58bc3a2143/src/Action.js#L6

Hiding the error and make it catchable only subscribing to the error event on the flux instance feels a bit weird to me, especially if I don't know that I can do it just because I'm too lazy to read the docs :)

This is just my 2 cents, your solution work pretty well by the way.
Handling errors in promises is always a mess :)

from flummox.

acdlite avatar acdlite commented on July 28, 2024

even though [...] a promise is not supposed to throw, the reality is that it potentially could.

Not unless you do it intentionally using setTimeout(). All errors that occur inside a .then() callback are (by design) gobbled up and turned into a rejected promise. It's part of the spec.

I mean that if an error occurs the right thing to do is not hiding it, but make the system aware of it, in a natural way (rethrow)

That's the natural way to handle errors in synchronous code, because you can use try-catch. But try-catch doesn't work for errors that occur in separate ticks of the event loop, hence the common Node-style pattern of passing an error object as the first argument to a callback. (Even using ES7 async functions, which do allow you to use try-catch through some wonderful generator and promise magic, if an unhandled error occurs, the function returns a rejected promise.)

With promises, the natural way to handle errors is to reject. I agree it's kind of weird, and probably the most contentious part about promises, but (since error-throwing is a synchronous operation) it makes sense if you think of promises as occurring in a totally separate time dimension from its calling context.

In practical terms, the reason "rethrowing" an error using setTimeout() is bad is because there's no way to catch it after that, because it happens during the next tick. Which is obviously bad.

McFly does something similar.

Tell me, how would you catch the error on line 11 after it's thrown? :)

I think the best approach would be to surround that call with a try/catch block.

Wrapping in a try-catch block has the same effect as the second code snippet from my comment above.

All of this is not to say that I'm not open to figuring out a better way to handle errors in Flummox. I just don't think rethrowing is the right solution. For now, I would recommend using the error event so you can make your own decisions.

from flummox.

vesparny avatar vesparny commented on July 28, 2024

Tell me, how would you catch the error on line 11 after it's thrown? :)

I guess the only way do to so is to usewindow.onerror handler.

The one we are discussing about is probably the most controversial Promise part :)

Anyways, the goal of the issue was to have the ability to notice errors, this way we are now able to log somewhere errors deriving from a developer syntax error for instance. And this is good 👍

from flummox.

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.