How to get custom server-side error message with ecmascript-6 and fetch api?

一曲冷凌霜 提交于 2019-12-06 16:49:31

问题


When a client-side fetch request results in an error on the server side, I'd like to return an error code (400) and a custom message. I don't know how to retrieve both on the client-side elegantly using fetch and promises.

return fetch('/api/something')
    .then(response => response.json())
    .then(json => {
         console.log(json.message)
        // I only have access to the json here.
        // I'd also like to get the response status code 
        // (from the response object) and potentially 
        // throw an error complete with the custom message.
    })
    .catch(function(ex) {
        console.log('Unhandled Error! ', ex);
    });

Thanks!


回答1:


You only have access to the JSON string since that is what you returned from the onFulfill callback in your first .then(). A better approach would be to return a Promise.all() wrapper that resolves to an array with the original response object as well as the "resolved" JSON object:

return fetch('/api/something')
    .then(response => Promise.all([response, response.json()]))
    .then(([response, json]) => {
        if (response.status < 200 || response.status >= 300) {
            var error = new Error(json.message);
            error.response = response;
            throw error;
        }
        // Either continue "successful" processing:
        console.log('success!', json.message);
        // or return the message to seperate the processing for a followup .then()
        // return json.message;
    })
    .catch(function(ex) {
        console.log('Unhandled Error! ', ex);
    });



回答2:


Answering my own question.

Edit...

With help from Amit and Felix I've settled on the code below as it's easiest for me to read.

async function format(response) {
    const json = await response.json();
    return {response, json};
}

function checkStatus(response, json) {
    if (response.status < 200 || response.status >= 300) {
        var error = new Error(json.message);
        error.response = response;
        throw error;
    }
    return {response, json};
}

return fetch('/api/something')
    .then((response) => format(response))
    .then(({response, json}) => checkStatus(response, json))
    .then(({response, json}) => {
        console.log('Success!', json.message);
    })
    .catch((error) => {
        if (error && error.response) {
            console.log('error message', error.message);
        } else {
            console.log('Unhandled error!');
        }
    });

...End Edit

Promise.all would have worked for me as described here: How do I access previous promise results in a .then() chain?. However, I find that unreadable. So ES7 async functions to the rescue!

async function formatResponse(response) {
    var json = await response.json();
    response.json = json;
    return response;
}

function checkResponseStatus(response) {
    if (response.status >= 200 && response.status < 300) {
        return response;
    } else {
        var error = new Error(response.json.message);
        error.response = response;
        throw error;
    }
}

function handleResponse(response) {
    console.log('success!', response.json);
}

function handleError(error) {
    if (error && error.response) {
        console.log('error message', error.message);
        console.log('error response code', error.response.status)
    } else {
        console.log('Unhandled error!');
    }
}

return fetch('/api/something')
   .then(formatResponse)
   .then(checkResponseStatus)
   .then(handleResponse)
   .catch(handleError);


来源:https://stackoverflow.com/questions/32511474/how-to-get-custom-server-side-error-message-with-ecmascript-6-and-fetch-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!