ReactJS asynchronous global API request method, how to handle response? - javascript

I am attempting to build a global API request function considering the repetitiveness of it. The problem I have is despite the responseBody object not being null when the function ends, the response seems to be null?
I can only assume this is in part due to the object being returned before it is updated.
Here is the function:
export function restRequest(url, method, content, body) {
fetch(API_BASE_URL + url, {
method: method,
headers: new Headers({
'Content-Type': content,
'Access-Control-Request-Method': method,
// 'Authorization': localStorage.getItem(ACCESS_TOKEN)
}),
body: body
}).then(
function (response) {
response.json().then((data) => {
let json = JSON.parse(JSON.stringify(data));
let responseBody = {
code: response.status,
body: json
};
//at this point the responseBody is not null
return responseBody;
});
}
)
.catch(function (err) {
console.log('Fetch Error :-S', err);
});
However if I make a call:
let response = restRequest('/app/rest/request', 'GET', 'application/json;charset=UTF-8', null);
response is always null.
What is the best way to handle this?

It's asynchronous, so any call of restRequest will not immediately return the responseBody = you need to properly chain the promises, and call .then on the restRequest call. Return the fetch call from the restRequest function, and avoid the promise-callback antipattern by returning response.json() immediately, rather than nesting a .then inside it:
export const restRequest = (url, method, content, body) => (
fetch(API_BASE_URL + url, {
method: method,
headers: new Headers({
'Content-Type': content,
'Access-Control-Request-Method': method,
// 'Authorization': localStorage.getItem(ACCESS_TOKEN)
}),
body
})
.then(response => Promise.all([response.status, response.json()])
.then(([code, body]) => ({ code, body }))
.catch(function(err) {
console.log('Fetch Error :-S', err);
})
);
then do
restRequest('/app/rest/request', 'GET', 'application/json;charset=UTF-8', null)
.then(response => {
// do stuff with response. (if there was an error, response will be undefined)
});

Related

Fetch won't return any results

I have never used fetch before, and have followed the documentation, however, no results are being returned from my backend. When I submit the form, the url changes, and all appears fine in my console, but no response from my express backend.
The following code is what I have after my form in a script tag. Can someone please advise?
async function getSample(url = `http://localhost:3000/lookup/${url}`, data = {}) {
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
return response.json();
}
document.getElementById('search').addEventListener('submit', function(e) {
event.respondWith(
new Response(myBody, {
headers: {'Content-Type': 'application/json'}
})
);
});
You could try creating a promise and then handling the value returned by the fetch with resolve and reject
async function getSample(url = `http://localhost:3000/lookup/${url}`, data = {}){
return new Promise(function (resolve, reject) {
fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}).then(async response => {
if (response.ok) {
response.json().then(json => resolve(json));
} else {
response.json().then(json => reject(json));
};
}).catch(async error => {
reject(error);
});
});
};
You would then call it like
getSample(...)
.then(results => {
//Code when fetch is successful
}.catch(error => {
//Code when fetch fails
};
I think the problem with it returning nothing is that getSample is an async function, but I imagine you're calling it within a program that isn't async, and so whatever code comes after getSample is using trying to use the value returned from getSample, but nothing's been returned yet, so it's using an empty value. Either that or the return of getSample is happening before the fetch completes. I'm not sure of the exact order that things happen, but a promise should fix your problem

React native : What is the way to take data from 1 function and pass it to function number 2?

What is the way to take data from getUserConnectRequestData function and pass it to getUserConnectResponseData function ?
as you can see so i try to use then and responseData to for save the data of the getUserConnectRequestData function and than i try pass it into the getUserConnectResponseData function but itd not works .
getUserConnectRequestData().then(() => {
responseData();
});
and this is getUserConnectResponseData function that i want to pass the data from getUserConnectRequestData
export const getUserConnectResponseData = (responseData) => {
return new Promise((resolve, reject) => {
// console.log('THIS IS MY RESPONSE ==============>>>>>>>>>>>', responseData);
try {
fetch(
'https://hghghgghghg3223223',
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
Req_Type: responseData.Req_Type,
Language_Code: responseData.Language_Code,
User_ID: responseData.User_ID,
Session_ID: responseData.Session_ID,
Session_Key: responseData.Session_Key,
Client_Type: responseData.Client_Type,
Req_Data: {
Bridge_ID: responseData.Bridge_ID,
},
}),
}
)
.then((response) => response.json())
.then((jsonResponse) => {
resolve(jsonResponse);
});
} catch (error) {
reject(error);
}
});
};
You need to accept the parameter and use it, and call the right function:
getUserConnectRequestData().then((responseData) => {
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^^^^^^^
getUserConnectResponseData(responseData);
// −^^^^^^^^^^^^^^^^^^^^^^^^^^−^^^^^^^^^^^^
});
But since getUserConnectResponseData takes just that one parameter you know that the then callback will only be called with that one single argument:
getUserConnectRequestData().then(getUserConnectResponseData);
You also need to handle errors, so:
getUserConnectRequestData()
.then(getUserConnectResponseData)
.catch(error => {
// Handle/report error
});
There are a couple of other things to point out, though:
getUserConnectRequestData is falling prey to a promise anti-pattern: You don't need new Promise when you already have a promise (from fetch) to use.
You need to check for HTTP success before calling .json() on the response. Sadly, fetch only rejects on network errors, not HTTP errors.
Here's an updated version of getUserConnectRequestData:
export const getUserConnectResponseData = (responseData) => {
return fetch('https://hghghgghghg3223223', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
Req_Type: responseData.Req_Type,
Language_Code: responseData.Language_Code,
User_ID: responseData.User_ID,
Session_ID: responseData.Session_ID,
Session_Key: responseData.Session_Key,
Client_Type: responseData.Client_Type,
Req_Data: {
Bridge_ID: responseData.Bridge_ID,
},
}),
})
.then((response) => {
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response.json();
});
};
Because of that need for the check, I never use fetch directly, I have wrappers to do the check so I don't have to code it Every Single Time.
// General purpose
function fetchGeneral(...args) {
return fetch(...args)
.then((response) => {
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response;
});
}
// JSON
function fetchJSON(...args) {
return fetch(...args)
.then((response) => {
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response.json();
});
}
Those reject on both network and HTTP errors.

Accessing promise data from Node API inside React fetch call

I'm putting together a React app that consumes data from a Node/Express REST API which is currently on my local machine. I've got a simple res.json returning a Sequelize object, and I'm accessing it through a service I made. Obviously, I'm going to be putting the object in state eventually, but I'm currently having difficulty accessing the values.
const options = {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: JSON.stringify({email: "matthewharp#gmail.com", password: "M1nerals"})
};
fetch('http://localhost:3000/users/sign_in', options)
.then(response => console.log(response.json()));
I'm getting the results in the console, but they're stuck in the [[PromiseValue]].
I must be missing some kind of async step, but I'm not sure what.
The json method returns a promise, which you also need to await. So do:
fetch('http://localhost:3000/users/sign_in', options)
.then(response => response.json())
.then(obj => console.log(obj));
You're having this error because response.json() return a promise.
you need to do
fetch('http://localhost:3000/users/sign_in', options)
.then(response => response.json())
.then(res => console.log(res));
You need to return the promise from the fetch call or else you need to act on it in the then for the json promise.
const options = {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: JSON.stringify({email: "matthewharp#gmail.com", password: "M1nerals"})
};
return fetch('http://localhost:3000/users/sign_in', options)
.then(response => {
console.log(response.json())
return response.json()
}
);
or...
const options = {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: JSON.stringify({email: "matthewharp#gmail.com", password: "M1nerals"})
};
fetch('http://localhost:3000/users/sign_in', options)
.then(response => {
console.log(response.json())
response.json().then( result => {
// whatever you're doing with the data here.
}
);
Take a look at the fetch api:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
You need a separate then chained to take the json data once ready, and it will give you the values.
('http://localhost:3000/users/sign_in', options)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(JSON.stringify(myJson));
});

Variable is showing undefined

I am hitting an api and saving response in a variable but the variable in which i am storing is showing undefined by debugger.
try {
let response = await fetch(
"http://test.kelltontech.net/eventengine/getmyevents?hash=****&timestamp=****&id=****",
{
method: "GET",
headers: {
"Content-Type": "application/json"
}
}
);
let responseJson = await response.json();
this.agendaDetails = await responseJson;
} catch (error) {
alert(error);
}
Here responseJson has data but not storing in agenda detail that is declared outside the main class like this agendaDetails={}
As an aside, and perhaps a better long term solution; instead of using fetch and wrapping it in a promise and making a tweak to return json. Use axios. It has promise support as standard and returns and expects json output.
let result = {};
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
result = response.data;
})
.catch(function (error) {
console.log(error);
});
Here is the link axios
you should use fetch with .then() to get response in json then assign that response to the variable just like below
fetch(URL.apiUrlUploadImages, {
method: "POST",
headers: {
Accept: 'application/json',
'Authorization': 'Bearer ' + this.token,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"front_image": this.frontImageData
})
})
.then((response) => response.json())
.then((responseData) => {
var result = responseData});

fetch fails to load resource when receiving 404

I got a method that fetches data from an API, but it logs errors when receiving an error response (404, 500).
I would just like to return 'undefined' as data if the status is an error, what's my mistake here, how do I get rid of the errors on my console?
fetch.js
export default (url, method, authorization, body) => {
const headers = { 'Content-Type': 'application/json' }
if (authorization) headers.Authorization = localStorage.getItem('id_token');
return fetch(url, {
method,
headers,
body: JSON.stringify(body)
}).then(res => res.ok ? res.json() : undefined)
.catch(console.log);
}
console
sources
I think Chrome always shows an error in the console when any request returns a HTTP error code in the 4XX or 5XX range, there's not much you can do about that.
The reason your catch isn't triggering is because when you return something in a then (or a catch) then that puts the promise chain back into a success mode. If you want to put it into a failure mode, and trigger the next catch, then you need to return specifically a rejected Promise:
Try this instead:
export default (url, method, authorization, body) => {
const headers = { 'Content-Type': 'application/json' }
if (authorization) headers.Authorization = localStorage.getItem('id_token')
return fetch(url, {
method,
headers,
body: JSON.stringify(body),
})
.then(res => {
res.ok ? res.json() : Promise.reject(undefined)
})
.catch(console.log)
}
Every time that you add the .catch() , the code go there if there is an error and skip the (res) => part.
So if you want to get rid of the errors of your console you can:
export default (url, method, authorization, body) => {
const headers = { 'Content-Type': 'application/json' }
if (authorization) headers.Authorization = localStorage.getItem('id_token');
return fetch(url, {
method,
headers,
body: JSON.stringify(body)
}).then(res => res.ok ? res.json(console.log(res)) : undefined) // check the result directly
}

Categories