Return json data from Function - json

I use a function for Fetch with below code :
var URL='...'
export function PostData(method,data){
fetch(URL+method,{
method:'POST',
body:JSON.stringify(data),
headers:{'Content-Type':'application/json'},
}).then(res => res.json())
.then(response => {
var ret=JSON.stringify(response)
return ret
})
.catch((error) => {
console.error(error)
})
}
and use it like below :
var retData=PostData('login/Authenticate',data)
retData is empty but in function ret has data

You PostData function does currently not return anything, so it is empty.
First step would be to add a return statement:
export function PostData(method,data){
return fetch(URL+method,{
method:'POST',
...
This will make your function return a value, but not just a simple value, but a promise! Promises are not the easiest to understand, but there is also a of people who tried to explain them
- https://developers.google.com/web/fundamentals/primers/promises
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Now how can you use the value anyway?
PostData('login/Authenticate',data)
.then(retData => {
// ... use retData here
});
Now, you used the react-native tag, so I am assuming you want to use this value in your render function. You can't do this simply by putting the PostData call in your render function. You'll have to put it in state, and then use that value in render:
state = { retData: null }
componentDidMount() {
PostData('login/Authenticate',data)
.then(retData => {
// This puts the data in the state after the request is done
this.setState({ retData: retData });
});
}
render() {
let retData = this.state.retData;
// ... use retData in your render here, will be `null` by default
There are a lot more different or cleaner ways to do this, but I tried to keep this answer as simple and bare as possible :)

It is empty at this point because the call to fetch is asynchronous and the literal is set to undefined as it moves to the next statement because it has not been resolved yet. One way around it is to return the promise object itself and then use .then to get the response once it is resolved.
var URL = '...'
export function PostData(method, data) {
// return the promise object
return fetch(URL + method, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
},
}).then(res => res.json())
.then(response => {
var ret = JSON.stringify(response)
return ret
})
.catch((error) => {
console.error(error)
})
}
PostData('login/Authenticate',data).then(response => {
// do something with the response
});
A cleaner approach would be is to use the async/await ES7 feature which makes it more readable.
var URL = '...'
export function PostData(method, data) {
// return the promise object
return fetch(URL + method, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json'
},
}).then(res => res.json())
.then(response => {
var ret = JSON.stringify(response)
return ret
})
.catch((error) => {
console.error(error)
})
}
async function getData() {
let retData = await PostData('login/Authenticate',data);
}

Related

LOG {"_U": 0, "_V": 0, "_W": null, "_X": null} inside fetch API

I am getting this error when I console data returned from function that fetch data from back end
{"_U": 0, "_V": 0, "_W": null, "_X": null}
here is below the code:
const events_data = [];
function getvals() {
return fetch('http://PCIP:3000/users/timetable')
.then((response) => response.json())
.then((output) => {
return addData(output, events_data);
})
.catch(error => console.log(error))
}
function addData(data, data2) {
data.map((d) => {
data2.push({
title: d.name,
startTime: genTimeBlock(d.day, d.start_time),
endTime: genTimeBlock(d.day, d.end_time),
location: d.location,
extra_descriptions: [d.extra_descriptions],
});
});
}
const data = getvals();
console.log(data); // the error come from here
I have checked answers here but nothing worked for me
fetch API always returns {“_U”: 0, “_V”: 0, “_W”: null, “_X”: null}
How do I access promise callback value outside of the function?
This is because the fetch promise has not return a response yet,
There two way to solve the issue , first you create another async funciton and use it to await for the response
const events_data = [];
async function getvals() {
return fetch('http://PCIP:3000/users/timetable')
.then((response) => response.json())
.then((output) => {
return addData(output, events_data);
})
.catch(error => console.log(error))
}
function addData(data, data2) {
data.map((d) => {
data2.push({
title: d.name,
startTime: genTimeBlock(d.day, d.start_time),
endTime: genTimeBlock(d.day, d.end_time),
location: d.location,
extra_descriptions: [d.extra_descriptions],
});
});
}
async function waitForResponse() {
let resp = await getvals();
return resp;
}
const data = waitForResponse();
console.log(data); // the error come from here
The other way would be using state hooks, passing the return obj to state hook on response.
Function for API call:
export const getApplication = async (URL, headers) => {
let data;
await fetch.get(URL, headers).then(res => data = res.data).catch(err => err);
return data;
}
You can call the API from anywhere after importing it:
getApplication(`your url`, {
headers: {
Authorization: AUTH_TOKEN,
},
}).then(res => console.log(res)).catch(err => console.log(err));

How to fix Cannot set headers after they are sent to the client?

After reading up on this topic for the last 2.5 hours I cant determine how to fix my: Cannot set headers after they are sent to the client issue, but I think it has to do with the below code at the bottom especially the code is in bold.
Any help or assistance will be greatly appreciated.
app.post("/api/tracking/retrieve", (req, res) => {
res.setHeader('Content-Type', 'application/json');
// before all the iterations
const trackingCodes = ['EZ6000000006', 'EZ4000000004'];
const carrierCodes = ['UPS', 'UPS'];
trackingCodes.forEach((trackingCode) => {
carrierCodes.forEach((carrierCode) => {
const tracker = new api.Tracker({
tracking_code: trackingCode,
carrier: carrierCode
})
tracker.save().then(function (data) {
table = 'tracking_table';
col = ['user_id', 'tracking_number'];
val = [user_id, tracker.tracking_code];
**// !ISSUE: :: ::: :::: ::::: :::::: ::::::: //**
main.create(table, col, val, function (data) {
res.send(JSON.stringify({
id: "",
user_id: user_id,
tracking_number: data.tracking_code
})); // replace this for your res.json()
});
}
)
.catch(error => {
// handle errors
console.log('There has been an error with your submission.')
});
})
})
res.end()
});
As #kiran Mathew has answered, the res.json() are called again and again inside for loop which is why 'cannot set headers after response sent' occurs.
You could have a result array 'trackingNumbers' to store all tracking_number and later exiting from the loop, sent a single response.
app.post("/api/tracking/retrieve", (req, res) => {
const trackingCodes = ["EZ6000000006", "EZ4000000004"];
const carrierCodes = ["UPS", "UPS"];
const trackingNumbers = [];
trackingCodes.forEach(trackingCode => {
carrierCodes.forEach(carrierCode => {
const tracker = new api.Tracker({
tracking_code: trackingCode,
carrier: carrierCode
});
tracker
.save()
.then(function(data) {
table = "tracking_table";
col = ["user_id", "tracking_number"];
val = [user_id, tracker.tracking_code];
// !ISSUE: :: ::: :::: ::::: :::::: ::::::: //**
main.create(table, col, val, function(data) {
// res.json({
// id: "",
// user_id: user_id,
// tracking_number: data.tracking_code
// });
trackingNumbers.push(data.tracking_code);
});
})
.catch(error => {
// handle errors
console.log("There has been an error with your submission.");
});
res.json({
id: "",
user_id: user_id,
tracking_number: trackingNumbers
});
});
});
});
The issue with your code is you are calling res.json() in an iterative loop.
You should call that only once since
res.json() implements res.write(),res.setHeaders() and res.end() under the hood,
which means once res.end() is called it ends the request and cannot send anymore.
You are better off writing the responses using
res.setHeader('Content-Type', 'application/json'); // before all the iterations
res.send(JSON.stringify({key:"value"})); // replace this for your res.json()
res.end() // after iterations

React Native - Second API Call is not returning value

My problem is that my code is returning an undefined value because of my second API Call:
render(){
const result_postid = this.state.data_one.map(function(val) {
return val.postid;
}).join(',');
const result_spaceid = this.state.data_one.map(function(vall) {
return vall.spaceid;
}).join(',');
//These two will receive values.
const result_image = this.state.data_two.map(function(valll) {
return valll.image;
}).join(',');
//This last one somehow will not receive value
}
Here I am fetching two APIs in the same componentDidMount:
componentDidMount(){
//First API Call
fetch(`http://www.exmaple.com/React/data.php`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
}).then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
data_one: responseJson,
},function() {
});
}).catch((error) => {
console.error(error);
});
// Second API Call
fetch(`http://www.example.com/React/image_data.php`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
}).then((response) => response.json())
.then((responseJson) => {
this.setState({
data_two: responseJson,
},function() {
});
}).catch((error) => {
console.error(error);
});
}
To confirm that it wasn't just a data response issue, I deleted the first to const (result_postid) and (result_spaceid) and the error was gone (TypeError: undefined is not a function (evaluating 'this.state.data_two.map(function(valll){return valll.image}')). The data showed successfully, but I need all 3 const to return the value. Is there a way to return all values for all 3 const?
The API calls are asynchronous, when you use the values in the render function some of them do not exist until all the calls return. You should have an initial state in the constructor
constructor(props) {
super(props);
this.state = {
data_one: [],
data_two: []
}
}
That way the values are not undefined. When the API returns the value, then the setState will trigger the render again.
Also, why do you have an empty function in the setState in the callbacks?
It should be something like
this.setState({
data_two: responseJson,
});
A couple of recommendations:
Use camelCase for variable naming, _ is not an usual standard in JS
Move the API calls to a different file, that will help you keep the component more organized. Then from componentDidMount you just call the function to make the request.

React + Fetch+ Json. TypeError: Cannot read property of undefined

When I used SuperAgent I didn't have this problem, but I decided to use Window.fetch polifyl and I met this problem. I see all data was loaded, but it still shows error.
Could your help me identify this error please:
In render() I genereate a list of components based on an obtained list:
render() {
if (this.state.data.list) {
console.log("render: " + this.state.data.list);
var counter = 0;
const list = this.state.data.list.map((item) => {
....
The promise handlers in your screenshot won't work:
.then((json) => console.log('parsed json: ', json))
.then((json) => { this.setState({ data: json }); })
"Take the value from resolving this promise and pass it to console.log. Then, take console.log's return value (which is undefined) and pass it to this.setState."
fetch(url, {
headers: {
'Accept': 'application/json',
},
}).then((response) => response.json()
.catch(err => {
console.err(`'${err}' happened!`);
return {};
}))
.then((json) => {
console.log('parsed json: ', json);
this.setState({ data: json })
})
.catch((err) => { console.log('fetch request failed: ', err) }
)

Aurelia typescript load json service

I am trying to create a class that will have two functions:
1) Load items from a json stored in my local server and return that variable with all the items.
2) Return a single item by id.
The problem is I want to use these two methods from different modules, and I do not know how to go about implementing the module and using it. So far, I have been able to implement the http part with aurelia's fetch client, but I don't know how to make the function:
function getItems() {
// some http request code
return fetchedItems;
}
Because the code in aurelia.io does something like this (which I have tried and actually works if I print the data):
import 'fetch';
import {HttpClient} from "aurelia-fetch-client";
export function getItems(url) {
let client = new HttpClient();
client.configure(config => {
config
.withBaseUrl('api/')
.withDefaults({
credentials: 'same-origin',
headers: {
'Accept': 'application/json',
'X-Requested-With': 'Fetch'
}
})
.withInterceptor({
request(request) {
console.log(`Requesting ${request.method} ${request.url}`);
return request;
},
response(response) {
console.log(`Received ${response.status} ${response.url}`);
return response;
}
});
});
client.fetch(url)
.then(response => response.json())
.then(data => {
console.log(data);
});
}
All this works ok. The point is that instead of doing 'console.log(data);' I want to return it, but so far the only thing that seems to work is assigning the returned items to a local class variable with 'this.items = data'. I would be ok with this so long as I get a function that allows to do this:
let items = getItems();
And
let item = getItemById(id);
EDIT: SOLVED
Users should note that, in order for this to work, they should have this in their tsconfig.js:
"target": "es6"
Because async/await requires at least ES2015.
Use async / await
If you're using TypeScript and targeting ES6, you can use the await/async keywords.
export async function getItems(url) {
let client = new HttpClient();
client.configure(config => {
config
.withBaseUrl('api/')
.withDefaults({
credentials: 'same-origin',
headers: {
'Accept': 'application/json',
'X-Requested-With': 'Fetch'
}
})
.withInterceptor({
request(request) {
console.log(`Requesting ${request.method} ${request.url}`);
return request;
},
response(response) {
console.log(`Received ${response.status} ${response.url}`);
return response;
}
});
});
return await client.fetch(url)
.then(response => response.json());
}
client.fetch returns a promise, so you just have to return it:
return client.fetch(url)
.then(response => response.json());
To use the function:
getItems(url)
.then(data => this.someProperty = data);