elbywan / wretch

A tiny wrapper built around fetch with an intuitive syntax. :candy:
MIT License
4.83k stars 98 forks source link

chaining catches and finaly catch any other errors. #111

Closed mkgn closed 3 years ago

mkgn commented 3 years ago

My basic setup of fetch goes like this;

window.wretch()
                .url()
                .headers()
                .auth()
                .catcher(401,
                    (error, request) => {
                        //do stuff;
                        }
                    }).catcher(403,
                    (error, request) => {
                        //do stuff;
                    }).fetchError(err => {
                     //trying to catch everything else here but fails 
                    });

So if i add .fetchError(), console throws an exception saying : TypeError: window.wretch().url(...).headers(...).auth(...).catcher(...).catcher(...).fetchError is not a function

So how can I wire this up to catch any other error after those two specific catches(401 & 403) ?

elbywan commented 3 years ago

Hi @mkgn,

fetchError is a function that catches only network errors, and it is meant to be used after resolving the request (after calling .json or .text or any body method, not before).

So how can I wire this up to catch any other error after those two specific catches(401 & 403) ?

Using .catch is an option:

wretch('https://httpstat.us/402')
  .catcher(401, (error, request) => {
    //do stuff;
  })
  .catcher(403, (error, request) => {
    //do stuff;
  })
  .get()
  .text(console.log)
   // Use .catch to catch up any other error
  .catch(error => console.error("Caught:", error));
mkgn commented 3 years ago

I see now that I am doing something wrong in general. Just to get it confirmed I will explain how mine works. I am using VueJS as front end.

So I have a common method in main vue app which will return a wretch() instance pre-configured (headers, jwt, content type etc..).. so it goes like this;

        fetcher: function (forApi=true) {
        if (!this.fetcherInstance) {
            this.fetcherInstance = window.wretch()
                .url((forApi) ? `${window.location.origin}/api` : window.location.origin)
                .headers({ "Content-Type": "application/json" })
                .auth(`Bearer ${(this.jwtToken) ? this.jwtToken.AccessToken : ""}`) // Authorization header
                .catcher(401,
                    (error, request) => {
                        debugger;
                        if (!this.jwtToken) //if no token for some reason can't refresh logout and force login
                            this.clearSessionAndRedirect();
                        else {
                            return this.refreshToken(request); //refresh and try to replay last call
                        }
                    }).catcher(403, (error, request) => {
                        debugger;
                        this.accessDeniedRedirect();
                    });
        }
        return this.fetcherInstance;
    },

Now in my other components I call my apis like;

                fetcher()
                .url("/1/tenant/tenant-master-data")
                .get()
                .json()
                .then(json => {
                    if (json && json.Success) {
                    }
                })

So from what you have mentioned, if I want to catch ALL errors; I need to add the catch() at component level methods and not at the main function which pre-configure the wretch?

elbywan commented 3 years ago

So from what you have mentioned, if I want to catch ALL errors; I need to add the catch() at component level methods and not at the main function which pre-configure the wretch?

Yes with Promises you need to catch after the .then call.

mkgn commented 3 years ago

Thank you! we can close this