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

Promise.catch example #904

Closed
nojaf opened this issue Aug 19, 2024 · 5 comments · Fixed by #910
Closed

Promise.catch example #904

nojaf opened this issue Aug 19, 2024 · 5 comments · Fixed by #910

Comments

@nojaf
Copy link
Contributor

nojaf commented Aug 19, 2024

Hi @fhammerschmidt,

https://rescript-lang.org/docs/manual/latest/promise is lacking a good sample on how to deal with Promise.catch blocks.

It is still a bit unclear to me what exn is. (Notice that I don't go to its definition in the IDE)
And how to unwrap exn to something useful. This works, but I'm not sure if it is idiomatic or not.

let f = async () => {
  Exn.raiseError("Hi!")
}
f()
->Promise.catch(async exn => {
  switch exn {
  | Exn.Error(exn) => exn->Exn.message->Option.getOr("yow")
  | _ => "no error"
  }
})
->Promise.done

Like, what else is there to catch if exn is not Exn.Error?

Would like to contribute a good example after receiving some guidance.

@fhammerschmidt
Copy link
Member

switch tries to match exhaustively, try/catch does not. And exceptions are extensible variants under the hood, which always expect a wildcard case since they are open-ended. So the better fit for exceptions is certainly try/catch syntax, or if you also return a value, switch/exception syntax.

See playground for examples

There is an example for Promise.catch in the API docs though: https://rescript-lang.org/docs/manual/latest/api/core/promise#value-catch-examples

About what's there to catch, you could also throw ReScript exceptions somewhere deeper in the corresponding function. Some are even built-in.

@nojaf
Copy link
Contributor Author

nojaf commented Aug 19, 2024

Thanks, this is interesting!

So

let tryCatchWay = async () =>
  try await f() catch {
  | Exn.Error(exn) => exn->Exn.message->Option.getOr("yow")
  }

// => no need for the `exception` keyword here? When do I need that in a case branch?

// And what happens if the thing is not an `Exn.Error`, Runtime error?

@fhammerschmidt
Copy link
Member

The exception keyword is only needed when you are switching on a function that may raise an exception. You certainly don't need it if you are already in the Promise.catch callback body and also never with try/catch. What it does is to wrap the function with try in the JS code.

@nojaf
Copy link
Contributor Author

nojaf commented Aug 20, 2024

Hmm, I guess the try/catch way does have most appeal.
However, you would need the async /await syntax.

How would this look like in an event listener?

// You can't make `async ev` because the handler would no longer fit
let onSubmit = ev => {
  somePromiseFn(blah)
  ->Promise.done
}

<form onSubmit={onSubmit}>...</form>

@fhammerschmidt
Copy link
Member

fhammerschmidt commented Aug 20, 2024

Promise.done is fine for simple event listeners (i.e. when you can just ignore the error).

But I have a helper function for more complex cases:

// PromiseUtils.res
let run = (makePromise: unit => promise<unit>) => makePromise()->Promise.done
// Other file
let onSubmit = ev => PromiseUtils.run(async () => 
  switch await someResultPromise() {
   | Ok(_data) => ()
   | Error(error) => 
     logError(error)
     showReadableErrorToUser(error)
  }
)

<form onSubmit={onSubmit}>...</form>

Also, most of my promises use result and not exceptions.

But I am not sure if this helper should be added to Core.Promise

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

Successfully merging a pull request may close this issue.

2 participants