Snackoverflow
Snackoverflow

Reputation: 828

Ajax generic request method, handling DELETE

I have this Ajax function:

function ajaxRequest(url, data, success, method) {
    return fetch(url, {
        method: method,
        body: JSON.stringify(data),
        headers: new Headers({
            'Content-Type': 'application/json'
        })
    }).then(res => res.json())
        .then(response => {
            if (response.status !== success) {
                throw response.status;
            }
            return response;
        })
        .catch(error => console.error('Error:', error, 'if you see this message, please report this error.'))
}

I pass 4 parameters to it:
url: The API end-point the request is sent to.
data: The data the API consumes. This could be an array of objects, or in this case, an ID of an object.
succes: The success code the server should return when executing the request. In this case 204.
method: The method Ajax should use, in this case DELETE.

Now when I use this function to send a DELETE request, it throws an error. This is because the server returns a 204, as expected, but other than that it is an empty response. So it tries to parse this as JSON, but fails since there is nothing to parse. I want to check before hand if the server returns a 204 and if it does, pass the response to the front-end. But if it doesn't I still want to parse it as JSON.

I tried implementing this with some if statements, but I ended up making 204's work and breaking the rest. I also thought about making a new Ajax request method just for delete requests, but to me it seems like you could make this work some how. I'm new to Ajax and I don't really understand the syntax I should use. If someone could show me how to do this I would appreciate it.

The error I get upon sending a delete request:

ajax.js:15 Error: SyntaxError: Unexpected end of JSON input
at fetch.then.res (ajax.js:8)
at <anonymous> if you see this message, please report this error.

Upvotes: 1

Views: 207

Answers (1)

Ferrybig
Ferrybig

Reputation: 18834

You should refactor the code to check for an 204 status code, before attempting to parse the response:

  1. We first make the XHR request using fetch
  2. Inside a then block, we check if the status code is 204 or 205
  3. In the no content case, we return an empty object, so downstream code can handle this situation correctly.
  4. We then handle HTTP errors using a throw new Error() block, instead of throwing the Number object, as this gives us a stacktrace.
return fetch(url, {
    method,
    body: JSON.stringify(data),
    headers: new Headers({
        'Content-Type': 'application/json'
    })
}).then((res) => {
    if (res.status === 204 || res.status === 205) {
        return {};
    } else if(res.status === 200 || res.status === 201){
        return res.json(); 
    } else {
        throw new Error('Problem making the request, server returned invalid status code: ' + res.status);
    }
});

Some other notable changes inside the code:

  • There is no longer a check for the success variable, as according to the HTTP spec, everthing in the range of 200 to 299 should be success
  • method has been writing inside the fetch object using the object shorthand notation
  • The error handling code has been removed from the promise chain, as handing failures should be done by the caller, because they are in the position to know what to do (like showing an error to the user, or re-trying)

Upvotes: 2

Related Questions