axios transformResponse returning undefined - javascript

With the following I get the expected response.data value:
axios({
method,
url
}).then(response => { console.log(response) })
However, when I add the transformResponse property as follows I get a response.data value of undefined:
axios({
method,
url,
transformResponse: [(data) => {
return data
}]
}).then(response => { console.log(response) })
Can someone please tell me what I'm missing here! Thanks

I suggest you to use interceptors since they are more clean
Interceptors work as a middlware on your requests
remove transformResponse and add this
axios.interceptors.response.use(function (response) {
return response.data;
});
axios({
method,
url,
}).then(response => { console.log(response) })

You can check the below sample to safe parse. transformResponse get data as raw staring so u can parse it.
const instance = axios.create({
baseURL: baseURL,
transformResponse: [
(data) => {
let resp;
try {
resp = JSON.parse(data);
} catch (error) {
throw Error(
`[requestClient] Error parsingJSON data - ${JSON.stringify(
error
)}`
);
}
if (resp.status === "success") {
return resp.data;
} else {
throw Error(`Request failed with reason - ${data}`);
}
},
],
});
Else you can use an interceptor to simplify it.
//const axios = require("axios");
const jsonInterceptor = [
(response) => response.data,
(error) => Promise.reject(error),
];
function jsonClient() {
const client = axios.create();
client.interceptors.response.use(...jsonInterceptor);
return client;
}
// Page 1
const jhttp = jsonClient();
jhttp
.get("https://jsonplaceholder.typicode.com/todos/1")
.then((data) => console.log(data));
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>

For anyone wondering here is the response:
axios.get(url, {
headers: {
'Content-Type': 'application/json'
},
transformResponse: axios.defaults.transformResponse.concat((data) => {
console.log(data) // this should now be JSON
})
})
from https://github.com/axios/axios/issues/430#issuecomment-243481806

Related

TypeError: res.json is not a function (not able to get fetch data)

I m trying to GET response using fetch API not stuck in a error as I mentioned below. Here's my code
const DefaultLayout = () => {
let history = useHistory()
const callHomePage = async () => {
try {
const res = fetch('http://localhost:4000/api/authenticate', {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-type': 'application/json',
},
credentials: 'include',
})
console.log(res)
const data = await res.json()
console.log(data)
if (!res.status === 200) {
const error = new Error(res.error)
throw error
}
} catch (err) {
console.log(err)
history.push('login')
}
}
Error: TypeError: res.json is not a function
Promise {} shows pending
const DefaultLayout = () => {
let history = useHistory()
const callHomePage = async () => {
try {
const res = await fetch('http://localhost:4000/api/authenticate', {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-type': 'application/json',
},
credentials: 'include',
})
console.log(res)
const data = await res.json()
console.log(data)
if (!res.status === 200) {
const error = new Error(res.error)
throw error
}
} catch (err) {
console.log(err)
history.push('login')
}
}
You need to await the fetch statement and then call the .json method of the response.
const res = await fetch(...)
data = await res.json();
Read more: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

JavaScript-ReactJS problem with GET fetch request ReactJS

I'm trying to doing a basic GET request from ReactJS app to a Node.js API, but I'm getting a response with status 304. I need get a 200 status to save the response of GET in a variable. (Im running Reactjs app in port 3000 and Nodejs API in port 3300)
Node API:
app.get('/serviciosextras', async (req, res) => {
let connection;
console.log(('Servicios Extras'));
try {
connection = await oracledb.getConnection({
user: 'portafolio',
password: '123',
connectString: "localhost:1521/orcl"
});
const result = await connection.execute(
`SELECT dep.id_departamento,
se.id_servicio,
se.precio_servicio
FROM departamento_servicio_detalle dsd
JOIN departamento DEP ON (dsd.id_departamento = dep.id_departamento)
JOIN servicio_extra SE ON (dsd.id_servicio = se.id_servicio)
ORDER BY 1 ASC`
)
const resultSet = result.rows;
let lista = [];
resultSet.map(obj => {
let serviciosSchema = {
'id_departamento': obj[0],
'id_servicio': obj[1],
'precio_servicio': obj[2]
}
lista.push(serviciosSchema);
});
console.log(lista);
res.json(lista);
connection.close();
} catch (err) {
console.error(err);
}
});
GET request from Reactjs
const getExtraServices = () => {
let endpoint = `${URL}serviciosextras`;
const requestOptions = {
method: "GET",
mode: 'no-cors'
// headers: {
// "Content-Type": "application/json",
// Accept: "application/json"
// },
};
console.log(endpoint);
fetch(endpoint, requestOptions)
.then((res, err) => {
console.log(res);
})
.then(result => {
console.log('fue aqui');
console.log(result);
})
.catch(err => {
console.log('ERROR');
console.log(err);
})
}
Im calling the method from this button:(onClick={getExtraServices()})
<Fab onClick={(e) => {
e.preventDefault();
getExtraServices();
}} variant="extended">
<NavigationIcon style={{marginRight: 'theme.spacing(1)'}} />
Navigate
</Fab>
so... I'm getting this:
Firefox Console when I clicked button to call getExtraServices() res is undefined
Network console of GET request I got a response but the status is 304, so I can't get this from code. :/
Console of Nodejs API this console.log if from console.log(lista) before send the res.json(lista)
Does someone know how can I fix this? I need get the response of the GET request to charge a list in ReactJS app, but I can't because the response has body:null.
Error 304 isn't the problem.
It looks like you are missing a statement to turn your response into JSON.
Here's an example from MDN:
fetch('https://example.com/profile', {
method: 'POST', // or 'PUT'
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
In particular:
.then(response => response.json())
In your code:
fetch(endpoint, requestOptions)
.then((res, err) => {
console.log(res); // logging res
// no data being returned here
})
.then(result => {
console.log('fue aqui');
console.log(result); // therefore result is undefined
})
.catch(err => {
console.log('ERROR');
console.log(err);
})

Javascript in VueJs: how to return data object from async fetch instead of Promise

I have this action in store
actions: {
testLogin(context, credentials) {
const loginService = new FetchClient();
let d = loginService.post('login', credentials);
console.log(d);
},
and this function in another class imported to store
async post(endpoint, params) {
await fetch(this.url + endpoint, {
'method': 'POST',
headers: this.headers,
body: JSON.stringify(params),
})
.then(response => {
return response.json();
})
.then( (data) => {
this.returnData = data.data;
})
.catch(error => {
console.log(error);
});
return this.returnData;
}
And I get Promise {<pending>} which I can extract data from inside the fetch class but can't access data if I'm in the store because it's a Promise not an object. How can I solve this?
Put the return statement inside the second then block:
async post(endpoint, params) {
await fetch(this.url + endpoint, {
'method': 'POST',
headers: this.headers,
body: JSON.stringify(params),
})
.then(response => {
return response.json();
})
.then( (data) => {
this.returnData = data.data;
return this.returnData;
})
.catch(error => {
console.log(error);
});
}
I would even recommend you use the following code for better legibility:
async post(endpoint, params) {
const response = await fetch(this.url + endpoint, {
'method': 'POST',
headers: this.headers,
body: JSON.stringify(params),
})
if (!response.ok) {
const message = `An error has occured: ${response.status}`;
throw new Error(message);
}
const resp_data = await response.json()
return resp_data.data
}
Then call your method like so:
post(endpoint, params)
.then(data => {// do something with data})
.catch(error => {
error.message; // 'An error has occurred: 404'
});
refer to this async/await guide
Can you try:
async testLogin(context, credentials) {
const loginService = new FetchClient();
let d = await loginService.post('login', credentials);
console.log(d);
}
As #Ayudh mentioned, try the following code:
async post(endpoint, params) {
try{
let response = await fetch(this.url + endpoint, {
'method': 'POST',
headers: this.headers,
body: JSON.stringify(params),
});
let data = await response.json();
this.returnData = data.data;
}catch(e){
console.log(e);
}
return this.returnData;
}

Async/Await in fetch() how to handle errors

I have stripe async code in my React app, and trying to add error handling in my code but have no idea how to handle it. i know how to do it with .then() but async/await is new to me
EDITED
added .catch() i got errors in network tab in response tab.
but i can log it to console?
submit = async () => {
const { email, price, name, phone, city, street, country } = this.state;
let { token } = await this.props.stripe
.createToken({
name,
address_city: city,
address_line1: street,
address_country: country
})
.catch(err => {
console.log(err.response.data);
});
const data = {
token: token.id,
email,
price,
name,
phone,
city,
street,
country
};
let response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
}).catch(err => {
console.log(err.response.data);
});
console.log(response);
if (response.ok)
this.setState({
complete: true
});
};
thanks
Fetch detects only network errors. Other errors (401, 400, 500) should be manually caught and rejected.
await fetch("/charge/pay", headers).then((response) => {
if (response.status >= 400 && response.status < 600) {
throw new Error("Bad response from server");
}
return response;
}).then((returnedResponse) => {
// Your response to manipulate
this.setState({
complete: true
});
}).catch((error) => {
// Your error is here!
console.log(error)
});
If you are not comfortable with this limitation of fetch, try using axios.
var handleError = function (err) {
console.warn(err);
return new Response(JSON.stringify({
code: 400,
message: 'Stupid network Error'
}));
};
var getPost = async function () {
// Get the post data
var post = await (fetch('https://jsonplaceholder.typicode.com/posts/5').catch(handleError));
// Get the author
var response = await (fetch('https://jsonplaceholder.typicode.com/users/' + post.userId).catch(handleError));
if (response.ok) {
return response.json();
} else {
return Promise.reject(response);
}
};
You can either use try/catch just like normal, imperative programming:
try {
let response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
} catch(error) {
// Error handling here!
}
Or you can mix-and-match .catch() just like you do with promises:
let response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
}).catch(function(error) {
// Error handling here!
});
Wrap your await with try catch.
try {
let response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
console.log(response);
} catch (error) {
console.log(error);
}
This works if server returns { message: "some error" } but I'm trying to get it to support res.statusText too:
const path = '/api/1/users/me';
const opts = {};
const headers = {};
const body = JSON.stringify({});
const token = localStorage.getItem('token');
if (token) {
headers.Authorization = `Bearer ${token}`;
}
try {
const res = await fetch(path, {
method: opts.method || 'GET',
body,
headers
});
if (res.ok) {
return await (opts.raw ? res.text() : res.json());
}
const err = await res.json();
throw new Error(err.message || err.statusText);
} catch (err) {
throw new Error(err);
}
async function loginWithRedirect(payload: {
username: string;
password: string;
}) {
const resp = await (await fetch(`${env.API_URL}/api/auth/login`, {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify(payload),
credentials: "include",
})).json();
if (resp.error) {
dispatch({type: "ERROR", payload: resp.error.message});
} else {
dispatch({type: "LOGIN", payload: resp});
}
}
If response.ok is false you can throw an error then chain catch method after calling your function as follows
async function fetchData(){
const response = await fetch("/charge/pay", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
if(!response.ok){
const message = `An error occured: ${response.status}`;
throw new Error(message);
}
const data = await response.json();
return data;
}
fetchData()
.catch(err => console.log(err.message));
I write promise function for using fetch in async await.
const promisyFetch = (url, options) =>
new Promise((resolve, reject) => {
fetch(url, options)
.then((response) => response.text())
.then((result) => resolve(result))
.catch((error) => reject(error));
});
By the way i can use it easly in async with try catch
const foo = async()=>{
try {
const result = await promisyFetch('url' requestOptions)
console.log(result)
} catch (error) {
console.log(error)
}
}
It was simple example, you could customize promisyFetch function and request options as you wish.
const data = {
token: token.id,
email,
price,
name,
phone,
city,
street,
country
};
axios
.post("/charge/pay", data)
.then(res => {
console.log(res);
})
.catch(err => {
console.log(err.response.data);
});

Fetch API error handling

I want to display error message from my API, problem is that I can't reach that error if I check for response.ok, it returns Fetch error, not the one from API..
If I don't use if(response.ok)... it returns the error from API but it dispatches the success action.
Here is the example, login action:
export const signIn = data => dispatch => {
dispatch({
type: SIGN_IN
})
fetch(API_URL+'/login', {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(data),
})
.then( response => {
if (!response.ok) { throw response }
return response.json() //we only get here if there is no error
})
.then( json => {
dispatch({
type: SIGN_IN_SUCCESS, payload: json
}),
localStorage.setItem("token", 'Bearer '+json.token)
localStorage.setItem("user", JSON.stringify(json.user))
})
.catch( err => {
dispatch({
type: SIGN_IN_FAILED, payload: err
})
})
}
This is the code for action that dispatches the right message but as success action, not as failed one..
export const signIn = data => dispatch => {
dispatch({
type: SIGN_IN
})
fetch(API_URL+'/login', {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(data),
})
.then( response => response.json())
.then( json => {
dispatch({
type: SIGN_IN_SUCCESS, payload: json
}),
localStorage.setItem("token", 'Bearer '+json.token)
localStorage.setItem("user", JSON.stringify(json.user))
})
.catch( err => {
dispatch({
type: SIGN_IN_FAILED, payload: err
})
})
}
With the following solution one can handle JSON API error, Generic API error and Generic fetch error
fetch("api/v1/demo", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"data": "demo"
})
})
.then(response => {
if (!response.ok) {
return Promise.reject(response);
}
return response.json();
})
.then(data => {
console.log("Success");
console.log(data);
})
.catch(error => {
if (typeof error.json === "function") {
error.json().then(jsonError => {
console.log("Json error from API");
console.log(jsonError);
}).catch(genericError => {
console.log("Generic error from API");
console.log(error.statusText);
});
} else {
console.log("Fetch error");
console.log(error);
}
});
according to This Article :
Per MDN, the fetch() API only rejects a promise when
“a network
error is encountered, although this usually means permissions issues
or similar.”
Basically fetch() will only reject a promise if the user
is offline, or some unlikely networking error occurs, such a DNS
lookup failure.
then, you can use this part of code to use non-network error handlings and make your code more readable
function handleErrors(response) {
if (!response.ok) throw new Error(response.status);
return response;
}
fetch("API URL")
// handle network err/success
.then(handleErrors)
// use response of network on fetch Promise resolve
.then(response => console.log("ok") )
// handle fetch Promise error
.catch(error => console.log(error) );
In order to extract API message from server in case of some error, you have to use the following idiom (which doesn't lie on the surface though), see link
fetch("http://localhost:8090/test/error", {
method: 'GET',
headers: {
'Accept': 'application/json'
}
})
.then(result => {
//Here body is not ready yet, throw promise
if (!result.ok) throw result;
return result.json();
})
.then(result => {
//Successful request processing
console.log(result);
}).catch(error => {
//Here is still promise
console.log(error);
error.json().then((body) => {
//Here is already the payload from API
console.log(body);
});
})
Verbose - yes!, but does exactly what is needed.

Categories

Resources