Fetch is the “de facto” standard now if building a new javascript code. Even if not yet supported by all browsers it is warmly recommended. There are numerous examples of usage but after reading a lot of them most of them seemed to miss the answer to my questions. These where:

  • how to proper do error handling including having a default error handler which can be overriden
  • how to do http POST?
  • how to use in real-life application? I mean one would expect to do a fetch for a login api and then all other api to work (i.e. have cookie support).

The following code (typescript) will try to answer the above questions:

<pre lang="javascript">function myFetch(path: string, params: Object, customCatch: boolean = false): Promise {
    let requestParams: RequestInit = {
        mode: 'cors',
        cache: 'default',
        credentials: 'include' //this is REQUIRED to enable cookie management
    };

    requestParams.body = $.params(object); //generate a query string: 'param1=val&param2=val';
    requestParams.headers = {
        "Content-type": "application/x-www-form-urlencoded; charset=UTF-8" //this is REQUIRED for POST with this payload
    };
    requestParams.method = 'POST';

    return fetch(path, requestParams)
        .then(response => {
            if (response.ok) {
                return response.text();
            } else {
                throw (response);
            }
        })
        .catch(err => {
            //please note that "TYPEERROR: FAILED TO FETCH" is a very BAD error message. From the spec:
            //"A fetch() promise will reject with a TypeError when a network error is encountered, 
            //although this usually means permission issues or similar"
            if (customCatch) {
                //this allows to override error handler with a custom function
                throw (err);
            } else {
                if (err instanceof Response) { //server error code, thrown from else above
                    //handle this error
                } else { //this is network error
                    //handle this error
                }
            }
            return null;
        });
}

//fetch with default error handling
myFetch('/api', {user: 'toto', task: 'info'})
    .then(
        response => {
            if(response != null){
                //handle response
            }
        });

//fetch with custom error handling
myFetch('/api', {user: 'toto', task: 'info'}, true)
    .then(
        response => {
            if(response != null){
                //handle response
            }
        })
    .catch(errResponse => {
        //handler errResponse (both error status and network error)
    })