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

Possibility of adding a global error handler on the web client? #301

Closed
enriquein opened this issue May 26, 2022 · 3 comments
Closed

Possibility of adding a global error handler on the web client? #301

enriquein opened this issue May 26, 2022 · 3 comments

Comments

@enriquein
Copy link

Hello 😄. I was wondering if there could be a way to add an error handler to the web proxies just like we can have them in the server side. My specific use case for this would be that I want to perform a specific set of actions if any of the endpoints at any point return 401/UnAuthorized. At the moment I'm using React.useDeferred and React.useDeferredCallback from Feliz, so I wrote a function that does the set of actions if the ProxyRequestException has a StatusCode of 401. The issue is that in order for me to implement it, at the moment I need to place the function in each match block where I check the status of the deferred value. I worry that at some point someone in my team might forget to set the function properly, since we're used to using interceptors in other frameworks/libraries for these concerns.

Something like this maybe:

let musicStore = 
    Remoting.createApi()
    |> Remoting.withErrorHandler errorHandler  // to make the API similar/consistent with the server counterpart
    |> Remoting.buildproxy<IMusicStore>
@enriquein
Copy link
Author

enriquein commented Jul 2, 2022

Decided to take a stab at this and landed on what I think is a good happy medium. Instead of a global error handler, I made it possible to add a global interceptor in PR #303. Hope this is useful to more people.

@Zaid-Ajaj
Copy link
Owner

Zaid-Ajaj commented Aug 3, 2022

Hi there @enriquein, so this problem has popped before and in fact, we did have a similar feature to what you implemented in #303 (it was years ago when we still used CEs for remoting builders),

The reason we removed was so that we do encourage users to NOT handle errors globally. An error is ideally handled at the place where it happens. That said, it is sometimes useful to have a global error handler and the current API already allows for it. Let me explain, so instead of using an instance of a protocol API, let's call that IServerApi, you WRAP the function in another function that handles global errors and exceptions:

module Api

// creata an instance of the protocol record
let serverApi = 
    Remoting.createApi()
    |> Remoting.buildproxy<IServerApi>

// wrap it here to handle global errors
let call (f: IServerApi -> Async<'t>) = 
  async {
      try
        let! result = f serverApi
        return (Some result)
      with
      | ex -> 
          // Do something global
          // show toast
          // redirect to login
          return None
  }

Now instead of Api.serverApi.funcName() you would write Api.call (fun api -> api.funcName())

Yes, a bit more code but does what you need to do in this instance. Also you could make call return a union of things you care about, not just Option<'t>.

You could also implement variants of Api.call such as Api.callWithIntercepter f intercepter where intercepter is statusCode -> responceBody -> unit and so on.

I hope this helps 🙏

@enriquein
Copy link
Author

I can't believe it never occurred to me to wrap the API 😅

Thank you for your feedback! Maybe we could add this somewhere in the docs so future generations don't reimplement this feature as well.

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

No branches or pull requests

2 participants