fetch api get error messages from server rather than generic messages - javascript

I'm using redux thunk to fetch some data in an action
function handleErrors(response) {
console.log(response)
if (!response.ok) {
throw Error(response.statusText);
}
return response;
}
export const something = (var) => dispatch => {
fetch(`${url}/something`, {credentials: 'include'})
.then(handleErrors)
.then(res => res.json())
.then(res =>
dispatch({
type: SOMETHING,
payload: res
})
)
.catch(error =>
dispatch({
type: ERROR,
payload: error
})
)
my express server on an error responds with 'some error'
return res.status(500).send({ message: 'some error' });
when it fetches and it's an error (500), its message is the generic "Internal Server Error".
how do I get the 'some error' in fetch?

Not sure what’s in your handleError. One approach to extract the error message would be something like this
fetch(url)
.then(res => {
// Check if response has errors
if (res.ok) {
// No errors
return res.json();
} else {
// Has errors, since res.json() returns a Promise, we
// chain a then here to get the value and return the err value
// as Promise rejection so that it will go to the
// catch handler
return res.json().then(err => Promise.reject(err));
// this could also be
// return res.json().then(err => throw Error(err));
}
})
.then(json => {
// dispatch success
})
.catch(err => {
// dispatch error
});

Related

Managing fetch errors with catch() doesn't work [duplicate]

Here's what I have going:
import 'whatwg-fetch';
function fetchVehicle(id) {
return dispatch => {
return dispatch({
type: 'FETCH_VEHICLE',
payload: fetch(`http://swapi.co/api/vehicles/${id}/`)
.then(status)
.then(res => res.json())
.catch(error => {
throw(error);
})
});
};
}
function status(res) {
if (!res.ok) {
return Promise.reject()
}
return res;
}
EDIT: The promise doesn't get rejected, that's what I'm trying to figure out.
I'm using this fetch polyfill in Redux with redux-promise-middleware.
Fetch promises only reject with a TypeError when a network error occurs. Since 4xx and 5xx responses aren't network errors, there's nothing to catch. You'll need to throw an error yourself to use Promise#catch.
A fetch Response conveniently supplies an ok , which tells you whether the request succeeded. Something like this should do the trick:
fetch(url).then((response) => {
if (response.ok) {
return response.json();
}
throw new Error('Something went wrong');
})
.then((responseJson) => {
// Do something with the response
})
.catch((error) => {
console.log(error)
});
The following login with username and password example shows how to:
Check response.ok
reject if not OK, instead of throw an error
Further process any error hints from server, e.g. validation issues
login() {
const url = "https://example.com/api/users/login";
const headers = {
Accept: "application/json",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify({
email: this.username,
password: this.password,
}),
})
.then((response) => {
// 1. check response.ok
if (response.ok) {
return response.json();
}
return Promise.reject(response); // 2. reject instead of throw
})
.then((json) => {
// all good, token is ready
this.store.commit("token", json.access_token);
})
.catch((response) => {
console.log(response.status, response.statusText);
// 3. get error messages, if any
response.json().then((json: any) => {
console.log(json);
})
});
},
Thanks for the help everyone, rejecting the promise in .catch() solved my issue:
export function fetchVehicle(id) {
return dispatch => {
return dispatch({
type: 'FETCH_VEHICLE',
payload: fetch(`http://swapi.co/api/vehicles/${id}/`)
.then(status)
.then(res => res.json())
.catch(error => {
return Promise.reject()
})
});
};
}
function status(res) {
if (!res.ok) {
throw new Error(res.statusText);
}
return res;
}
For me,
fny answers really got it all. since fetch is not throwing error, we need to throw/handle the error ourselves.
Posting my solution with async/await. I think it's more strait forward and readable
Solution 1: Not throwing an error, handle the error ourselves
async _fetch(request) {
const fetchResult = await fetch(request); //Making the req
const result = await fetchResult.json(); // parsing the response
if (fetchResult.ok) {
return result; // return success object
}
const responseError = {
type: 'Error',
message: result.message || 'Something went wrong',
data: result.data || '',
code: result.code || '',
};
const error = new Error();
error.info = responseError;
return (error);
}
Here if we getting an error, we are building an error object, plain JS object and returning it, the con is that we need to handle it outside.
How to use:
const userSaved = await apiCall(data); // calling fetch
if (userSaved instanceof Error) {
debug.log('Failed saving user', userSaved); // handle error
return;
}
debug.log('Success saving user', userSaved); // handle success
Solution 2: Throwing an error, using try/catch
async _fetch(request) {
const fetchResult = await fetch(request);
const result = await fetchResult.json();
if (fetchResult.ok) {
return result;
}
const responseError = {
type: 'Error',
message: result.message || 'Something went wrong',
data: result.data || '',
code: result.code || '',
};
let error = new Error();
error = { ...error, ...responseError };
throw (error);
}
Here we are throwing and error that we created, since Error ctor approve only string, Im creating the plain Error js object, and the use will be:
try {
const userSaved = await apiCall(data); // calling fetch
debug.log('Success saving user', userSaved); // handle success
} catch (e) {
debug.log('Failed saving user', userSaved); // handle error
}
Solution 3: Using customer error
async _fetch(request) {
const fetchResult = await fetch(request);
const result = await fetchResult.json();
if (fetchResult.ok) {
return result;
}
throw new ClassError(result.message, result.data, result.code);
}
And:
class ClassError extends Error {
constructor(message = 'Something went wrong', data = '', code = '') {
super();
this.message = message;
this.data = data;
this.code = code;
}
}
Hope it helped.
2021 TypeScript Answer
What I do is write a fetch wrapper that takes a generic and if the response is ok it will auto .json() and type assert the result, otherwise the wrapper throws the response
export const fetcher = async <T>(input: RequestInfo, init?: RequestInit) => {
const response = await fetch(input, init);
if (!response.ok) {
throw response;
}
return response.json() as Promise<T>;
};
and then I'll catch errors and check if they are an instanceof Response. That way TypeScript knows that error has Response properties such as status statusText body headers etc. and I can apply a custom message for each 4xx 5xx status code.
try {
return await fetcher<LoginResponse>("http://localhost:8080/login", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({ email: "user#example.com", password: "passw0rd" }),
});
} catch (error) {
if (error instanceof Response) {
switch (error.status) {
case 401:
throw new Error("Invalid login credentials");
/* ... */
default:
throw new Error(`Unknown server error occured: ${error.statusText}`);
}
}
throw new Error(`Something went wrong: ${error.message || error}`);
}
and if something like a network error occurs it can be caught outside of the instanceof Response check with a more generic message i.e.
throw new Error(`Something went wrong: ${error.message || error}`);
The answer by #fny (the accepted answer) didn't work for me. The throw new Error() wasn't getting picked up by the .catch. My solution was to wrap the fetch with a function that builds a new promise:
function my_fetch(url, args) {
return new Promise((resolve, reject) => {
fetch(url, args)
.then((response) => {
response.text().then((body) => {
if (response.ok) {
resolve(body)
} else {
reject(body)
}
})
})
.catch((error) => { reject(error) })
})
}
Now every error and non-ok return will be picked up by the .catch method:
my_fetch(url, args)
.then((response) => {
// Do something with the response
})
.catch((error) => {
// Do something with the error
})
function handleErrors(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
}
fetch("https://example.com/api/users")
.then(handleErrors)
.then(response => console.log("ok") )
.catch(error => console.log(error) );
I wasn't satisfied with any of the suggested solutions, so I played a bit with Fetch API to find a way to handle both success responses and error responses.
Plan was to get {status: XXX, message: 'a message'} format as a result in both cases.
Note: Success response can contain an empty body. In that case we fallback and use Response.status and Response.statusText to populate resulting response object.
fetch(url)
.then(handleResponse)
.then((responseJson) => {
// Do something with the response
})
.catch((error) => {
console.log(error)
});
export const handleResponse = (res) => {
if (!res.ok) {
return res
.text()
.then(result => JSON.parse(result))
.then(result => Promise.reject({ status: result.status, message: result.message }));
}
return res
.json()
.then(result => Promise.resolve(result))
.catch(() => Promise.resolve({ status: res.status, message: res.statusText }));
};
I just checked the status of the response object:
$promise.then( function successCallback(response) {
console.log(response);
if (response.status === 200) { ... }
});
Hope this helps for me throw Error is not working
function handleErrors(response) {
if (!response.ok) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject({
status: response.status,
statusText: response.statusText,
});
}, 0);
});
}
return response.json();
}
function clickHandler(event) {
const textInput = input.value;
let output;
fetch(`${URL}${encodeURI(textInput)}`)
.then(handleErrors)
.then((json) => {
output = json.contents.translated;
console.log(output);
outputDiv.innerHTML = "<p>" + output + "</p>";
})
.catch((error) => alert(error.statusText));
}
Another (shorter) version that resonates with most answers:
fetch(url)
.then(response => response.ok ? response.json() : Promise.reject(response))
.then(json => doStuff(json)) //all good
//next line is optional
.catch(response => handleError(response)) //handle error

How to throw a Response when the return code is not 200?

I am writing a helper for my API calls and would like it to
pass a text() response when the call is successful
throw the full Response otherwise
The reason for this is that I have a case of an API call where a 404 is expected and would like to manage this specific case. Other 404 (in different calls) are indeed errors.
Consider the code below:
const apiCall = (url) => {
return fetch(url)
.then(r => {
if (r.ok) {
return r.text()
} else {
console.log('in apiCall → then(), fetch soft-failed, passing error downstream')
throw Error(r.statusText) // this works but is not what I want, I want to throw "r"
}
})
.catch(err => {
console.log('in apiCall → catch(), passing error downstream')
throw err
})
}
apiCall('http://httpstat.us/200')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err}`))
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err}`)) // this works but I obviously got a statusText and not an r
This outputs
in apiCall → then(), fetch soft-failed, passing error downstream
in apiCall → catch(), passing error downstream
the return code was Error: Not Found
200 OK
What I would like to do is for one call where the 404 is expected (this is incorrect code in the context of the code above)
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => {
if (err.Code == 404) {
// it is OK
} else {
// it is not OK
}
})
and for another call where any non-2xx response is incorrect :
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => {
// not OK
})
How can I throw the Response and not only text?
In other words, the code I would like to have:
const apiCall = (url) => {
return fetch(url)
.then(r => {
if (r.ok) {
return r.text()
} else {
console.log('in apiCall → then(), fetch soft-failed, passing error downstream')
throw r
}
})
.catch(err => {
console.log('in apiCall → catch(), passing error downstream')
throw err // I would need to manage actual errors (network, ...)
})
}
apiCall('http://httpstat.us/200')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err.Code}`))
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err.Code}`))
but this outputs undefined
in apiCall → then(), fetch soft-failed, passing error downstream
in apiCall → catch(), passing error downstream
the return code was undefined
200 OK
You can add an argument as expectedFailureCodes and check the request code after it fails. If it is well expected then you can handle it as you like.
import fetch from "node-fetch";
const apiCall = (url, expectedFailureCodes=[]) => {
return fetch(url)
.then(async res => {
if (res.ok) return res
else if (expectedFailureCodes.includes(res.status)) {
return {
passedIntentionally: true,
res
}
}
else throw new Error(JSON.stringify({
status: res.status,
body: await res.text()
}))
})
.catch(err => {
throw err
})
}
apiCall("http://httpstat.us/404", [404]).then(res => {
console.log(res)
})
apiCall("http://httpstat.us/404", ).catch(err => {
console.log(err)
})
apiCall("http://httpstat.us/200", ).then(res => {
console.log(res)
})
Well, throwing r works fine, you were just logging the wrong property. The status code can be accessed via r.status:
const apiCall = (url) => {
return fetch(url)
.then(r => {
if (r.ok) {
return r.text()
} else {
console.log('in apiCall → then(), fetch soft-failed, passing error downstream')
throw r
}
})
.catch(err => {
console.log('in apiCall → catch(), passing error downstream')
throw err // I would need to manage actual errors (network, ...)
})
}
apiCall('http://httpstat.us/200')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err.status}`))
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => console.log(`the return code was ${err.status}`))
The only problem with that approach is, that your code won't know how to handle "hard errors" (network errors or runtime errors in the code). You can identify those with "duck typing methods" (if it has a status property, it must be a Response object...), but a better solution would be to have a custom Error class:
class HTTPError extends Error{
constructor(r){
super(`HTTP ${r.status} error`)
this.r = r
}
}
const apiCall = (url) => {
return fetch(url)
.then(r => {
if (r.ok) {
return r.text()
} else {
console.log('in apiCall → then(), fetch soft-failed, passing error downstream')
throw new HTTPError(r)
}
})
.catch(err => {
console.log('in apiCall → catch(), passing error downstream')
throw err
})
}
apiCall('http://httpstat.us/200')
.then(r => console.log(r))
.catch(err => {
if(!(err instanceof HTTPError))
throw err //Other error
console.log(`the return code was ${err.r.status}`)
})
apiCall('http://httpstat.us/404')
.then(r => console.log(r))
.catch(err => {
if(!(err instanceof HTTPError))
throw err //Other error
//You can access `r` via `err.r` here
console.log(`the return code was ${err.r.status}`)
})

Getting unhandled Promise rejection when I already throw err in the catch block

In my redux I got this axios get call As you can see I already throw the err here
export const getShippingMethodById = (token, id) => {
return (dispatch) => {
const config = {
headers: {
Authorization: `bearer ${token}`,
'Content-Type': 'application/json',
},
};
return axios
.get(`${baseUri}/api/checkout/GetShippingById?addressId=${id}`, config)
.then((res) => {
dispatch({
type: FETCH_SHIPPING_METHOD_BY_ID,
payload: res.data.shippingInfos,
});
})
.catch((err) => {
console.log(err);
throw err;
alert('Cannot connect to server');
});
};
};
In the functional component , inside the useEffect hooks I am calling this function
useEffect(() => {
let splitText = cartList?.OrderDTO?.DeliveryCountry;
let deliveryAddressId = splitText?.split(',');
if (
cartList.OrderDTO?.DeliveryCountry !== '' &&
deliveryAddressId !== undefined
) {
dispatch(
getShippingMethodById(token.access_token, Number(deliveryAddressId[1])),
).then((res) => {
console.log(res);
});
} else {
dispatch(
getShippingMethodById(
token.access_token,
cartList.OrderDTO?.CustomerAddressId,
),
).then((res) => {
console.log(res);
});
}
}, [cartList]);
But when ever this component is loaded
I got this error
Since I already handle the promise rejection Why am I getting this error?
Because you are using throw err; in catch block. You need to remove it. You can read more about throw in here: https://developer.mozilla.org/vi/docs/Web/JavaScript/Reference/Statements/throw
Throwing an error from a catch won't be caught by the same catch block being executed. This means you are returning a Promise rejection to your UI code and the error should then be caught there. Add a catch to the Promise chain.
useEffect(() => {
let splitText = cartList?.OrderDTO?.DeliveryCountry;
let deliveryAddressId = splitText?.split(',');
if (
cartList.OrderDTO?.DeliveryCountry !== '' &&
deliveryAddressId !== undefined
) {
dispatch(
getShippingMethodById(token.access_token, Number(deliveryAddressId[1])),
).then((res) => {
console.log(res);
}).catch(error => {
// handle rejected Promise or any other error from this chain
});
} else {
dispatch(
getShippingMethodById(
token.access_token,
cartList.OrderDTO?.CustomerAddressId,
),
).then((res) => {
console.log(res);
}).catch(error => {
// handle rejected Promise or any other error from this chain
});
}
}, [cartList]);
Or simply remove rethrowing the error:
return axios
.get(`${baseUri}/api/checkout/GetShippingById?addressId=${id}`, config)
.then((res) => {
dispatch({
type: FETCH_SHIPPING_METHOD_BY_ID,
payload: res.data.shippingInfos,
});
})
.catch((err) => {
console.log(err);
// no error rethrow
alert('Cannot connect to server');
});

Exsport function with Api call then import it on another page and wait for data

I'm new to all this export, import, async so please bare with me.
I have one file where I make API call and export that function so it can be used across other pages.
Of course on other page when function is invoked data payload is not yet there so i get undefind. So i tried to implement async (first time).
Please correct me if this is even possible or I I need some other method.
app.js:
export function inboxMeniIkona () {
//let req = xxxx
fetch(req)
.then(response => {
if (response.ok) {
return response.json()
} else {
throw new Error('NETWORK RESPONSE ERROR')
}
})
.then(data => {
return new Promise(resolve => {
return data // data here is allright
});
})
.catch(error => console.error('FETCH ERROR:', error))
}
And then I tried on other page:
import { inboxMeniIkona } from '~/app'
async function asyncCall() {
console.log('calling');
const result = await inboxMeniIkona();
console.log(result);
// expected output: "resolved"
}
asyncCall();
I'm still getting
CONSOLE LOG: calling
CONSOLE LOG: undefined
Please advise
Add async in your functions and await in your fecth and return it like this.
export async function inboxMeniIkona () {
//let req = xxxx
return await fetch(req)
.then(response => {
if (response.ok) {
return response.json()
} else {
throw new Error('NETWORK RESPONSE ERROR')
}
})
.then(data => {
return data // data here is allright
})
.catch(error => console.error('FETCH ERROR:', error))
}

Fetch: reject promise and catch the error if status is not OK?

Here's what I have going:
import 'whatwg-fetch';
function fetchVehicle(id) {
return dispatch => {
return dispatch({
type: 'FETCH_VEHICLE',
payload: fetch(`http://swapi.co/api/vehicles/${id}/`)
.then(status)
.then(res => res.json())
.catch(error => {
throw(error);
})
});
};
}
function status(res) {
if (!res.ok) {
return Promise.reject()
}
return res;
}
EDIT: The promise doesn't get rejected, that's what I'm trying to figure out.
I'm using this fetch polyfill in Redux with redux-promise-middleware.
Fetch promises only reject with a TypeError when a network error occurs. Since 4xx and 5xx responses aren't network errors, there's nothing to catch. You'll need to throw an error yourself to use Promise#catch.
A fetch Response conveniently supplies an ok , which tells you whether the request succeeded. Something like this should do the trick:
fetch(url).then((response) => {
if (response.ok) {
return response.json();
}
throw new Error('Something went wrong');
})
.then((responseJson) => {
// Do something with the response
})
.catch((error) => {
console.log(error)
});
The following login with username and password example shows how to:
Check response.ok
reject if not OK, instead of throw an error
Further process any error hints from server, e.g. validation issues
login() {
const url = "https://example.com/api/users/login";
const headers = {
Accept: "application/json",
"Content-Type": "application/json",
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify({
email: this.username,
password: this.password,
}),
})
.then((response) => {
// 1. check response.ok
if (response.ok) {
return response.json();
}
return Promise.reject(response); // 2. reject instead of throw
})
.then((json) => {
// all good, token is ready
this.store.commit("token", json.access_token);
})
.catch((response) => {
console.log(response.status, response.statusText);
// 3. get error messages, if any
response.json().then((json: any) => {
console.log(json);
})
});
},
Thanks for the help everyone, rejecting the promise in .catch() solved my issue:
export function fetchVehicle(id) {
return dispatch => {
return dispatch({
type: 'FETCH_VEHICLE',
payload: fetch(`http://swapi.co/api/vehicles/${id}/`)
.then(status)
.then(res => res.json())
.catch(error => {
return Promise.reject()
})
});
};
}
function status(res) {
if (!res.ok) {
throw new Error(res.statusText);
}
return res;
}
For me,
fny answers really got it all. since fetch is not throwing error, we need to throw/handle the error ourselves.
Posting my solution with async/await. I think it's more strait forward and readable
Solution 1: Not throwing an error, handle the error ourselves
async _fetch(request) {
const fetchResult = await fetch(request); //Making the req
const result = await fetchResult.json(); // parsing the response
if (fetchResult.ok) {
return result; // return success object
}
const responseError = {
type: 'Error',
message: result.message || 'Something went wrong',
data: result.data || '',
code: result.code || '',
};
const error = new Error();
error.info = responseError;
return (error);
}
Here if we getting an error, we are building an error object, plain JS object and returning it, the con is that we need to handle it outside.
How to use:
const userSaved = await apiCall(data); // calling fetch
if (userSaved instanceof Error) {
debug.log('Failed saving user', userSaved); // handle error
return;
}
debug.log('Success saving user', userSaved); // handle success
Solution 2: Throwing an error, using try/catch
async _fetch(request) {
const fetchResult = await fetch(request);
const result = await fetchResult.json();
if (fetchResult.ok) {
return result;
}
const responseError = {
type: 'Error',
message: result.message || 'Something went wrong',
data: result.data || '',
code: result.code || '',
};
let error = new Error();
error = { ...error, ...responseError };
throw (error);
}
Here we are throwing and error that we created, since Error ctor approve only string, Im creating the plain Error js object, and the use will be:
try {
const userSaved = await apiCall(data); // calling fetch
debug.log('Success saving user', userSaved); // handle success
} catch (e) {
debug.log('Failed saving user', userSaved); // handle error
}
Solution 3: Using customer error
async _fetch(request) {
const fetchResult = await fetch(request);
const result = await fetchResult.json();
if (fetchResult.ok) {
return result;
}
throw new ClassError(result.message, result.data, result.code);
}
And:
class ClassError extends Error {
constructor(message = 'Something went wrong', data = '', code = '') {
super();
this.message = message;
this.data = data;
this.code = code;
}
}
Hope it helped.
2021 TypeScript Answer
What I do is write a fetch wrapper that takes a generic and if the response is ok it will auto .json() and type assert the result, otherwise the wrapper throws the response
export const fetcher = async <T>(input: RequestInfo, init?: RequestInit) => {
const response = await fetch(input, init);
if (!response.ok) {
throw response;
}
return response.json() as Promise<T>;
};
and then I'll catch errors and check if they are an instanceof Response. That way TypeScript knows that error has Response properties such as status statusText body headers etc. and I can apply a custom message for each 4xx 5xx status code.
try {
return await fetcher<LoginResponse>("http://localhost:8080/login", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({ email: "user#example.com", password: "passw0rd" }),
});
} catch (error) {
if (error instanceof Response) {
switch (error.status) {
case 401:
throw new Error("Invalid login credentials");
/* ... */
default:
throw new Error(`Unknown server error occured: ${error.statusText}`);
}
}
throw new Error(`Something went wrong: ${error.message || error}`);
}
and if something like a network error occurs it can be caught outside of the instanceof Response check with a more generic message i.e.
throw new Error(`Something went wrong: ${error.message || error}`);
The answer by #fny (the accepted answer) didn't work for me. The throw new Error() wasn't getting picked up by the .catch. My solution was to wrap the fetch with a function that builds a new promise:
function my_fetch(url, args) {
return new Promise((resolve, reject) => {
fetch(url, args)
.then((response) => {
response.text().then((body) => {
if (response.ok) {
resolve(body)
} else {
reject(body)
}
})
})
.catch((error) => { reject(error) })
})
}
Now every error and non-ok return will be picked up by the .catch method:
my_fetch(url, args)
.then((response) => {
// Do something with the response
})
.catch((error) => {
// Do something with the error
})
function handleErrors(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
}
fetch("https://example.com/api/users")
.then(handleErrors)
.then(response => console.log("ok") )
.catch(error => console.log(error) );
I wasn't satisfied with any of the suggested solutions, so I played a bit with Fetch API to find a way to handle both success responses and error responses.
Plan was to get {status: XXX, message: 'a message'} format as a result in both cases.
Note: Success response can contain an empty body. In that case we fallback and use Response.status and Response.statusText to populate resulting response object.
fetch(url)
.then(handleResponse)
.then((responseJson) => {
// Do something with the response
})
.catch((error) => {
console.log(error)
});
export const handleResponse = (res) => {
if (!res.ok) {
return res
.text()
.then(result => JSON.parse(result))
.then(result => Promise.reject({ status: result.status, message: result.message }));
}
return res
.json()
.then(result => Promise.resolve(result))
.catch(() => Promise.resolve({ status: res.status, message: res.statusText }));
};
I just checked the status of the response object:
$promise.then( function successCallback(response) {
console.log(response);
if (response.status === 200) { ... }
});
Hope this helps for me throw Error is not working
function handleErrors(response) {
if (!response.ok) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject({
status: response.status,
statusText: response.statusText,
});
}, 0);
});
}
return response.json();
}
function clickHandler(event) {
const textInput = input.value;
let output;
fetch(`${URL}${encodeURI(textInput)}`)
.then(handleErrors)
.then((json) => {
output = json.contents.translated;
console.log(output);
outputDiv.innerHTML = "<p>" + output + "</p>";
})
.catch((error) => alert(error.statusText));
}
Another (shorter) version that resonates with most answers:
fetch(url)
.then(response => response.ok ? response.json() : Promise.reject(response))
.then(json => doStuff(json)) //all good
//next line is optional
.catch(response => handleError(response)) //handle error

Categories