Xstate: Resolving promise within invoke triggers onError

Created on 21 Nov 2018  ·  8Comments  ·  Source: davidkpiano/xstate

Bug

Description:

When using a promise as the value of src within invoke, if the promise resolves, onError is triggered.

Expected result:

onSuccess triggered

Actual result:

onError triggered

Potential fix:

Uncomment function fromPromise in xstate/src/invoke.ts

enhancement invalid

Most helpful comment

Funny enough, this is working as intended because there is an error ❌:

If you log out the event data from the error:

        onError: {
          target: "failure",
          actions: (_, e) => console.error(e.data)
        }

You will see:

Error: Child state 'success' does not exist on 'user'

And that's exactly what happened - you don't have a success state. Add it and it works 👍


I'm going to keep this open because I want to better handle what happens if you _don't_ have an onError handler and an error occurs anyway (the script should throw that exact error).

All 8 comments

Do you have a reproducible code example?

sure, codesandbox

Funny enough, this is working as intended because there is an error ❌:

If you log out the event data from the error:

        onError: {
          target: "failure",
          actions: (_, e) => console.error(e.data)
        }

You will see:

Error: Child state 'success' does not exist on 'user'

And that's exactly what happened - you don't have a success state. Add it and it works 👍


I'm going to keep this open because I want to better handle what happens if you _don't_ have an onError handler and an error occurs anyway (the script should throw that exact error).

That makes sense. I may have messed up the example when moving it to code sandbox but the source of the problem I had was using the property onSuccess instead of onDone, which logs out this error: Machine 'user' does not accept event 'done.invoke.promise'. Not sure where I picked up the onSuccess property, I see in the docs example it is onDone.

I also made the assumption thatonDone was synonymous with the JS promise method .finally, which triggers after success or error.

The names onDone and onError come from the SCXML Spec, which raises:

  • done.invoke.<id> when the invoked service has reached its final state
  • error.execution when errors occur during execution

In fact, you don't even need to use onDone and onError - these are just sugar for those SCXML event names:

{
  on: {
    'done.invoke.someID': 'success',
    'error.execution': {
      target: 'failure',
      cond: (ctx, e) => e.src === 'someID'
    }
  }
}

Interesting, the onDone & onError syntax is quite nice though.

Should be fixed in master thanks to @jjkola's work.

Was this page helpful?
0 / 5 - 0 ratings