json and data returned from api's - javascript

I'm new to coding and just paying around, but i have what I think is really simple problem, but just don't have the necessary vocabulary to express it properly. Here is my code, its for currency conversion.
app.get('/currency', (request, response) => {
const from_currency = request.query.from;
const to_currency = request.query.to;
const amount = request.query.amount;
const exchange = `${from_currency}_${to_currency}`
//https://free.currencyconverterapi.com/api/v5/convert?q=USD_PHP&compact=y
const currencyUrl = `https://free.currencyconverterapi.com/api/v5/convert?q=${from_currency}_${to_currency}&compact=y`;
const requestOptions = {
uri: currencyUrl,
json: true
};
requestPromise(requestOptions)
.then((data) => {
//const responseData = getCurrentCurrencyJSON(data);
response.json(data); //responseData
})
.catch((error) => {
console.log(error.message);
response.json({
messages: [{
text: 'Sorry there was an error!'
}]
});
});
});
This returns, from the API, {"USD_GBP":{"val":0.73897}}, which is fine and I can return the value if i write response.json(data.USD_GBP.val); however I want to be able to vary the currencies im converting to and from, so how do I make the USD_GBP in the response.json dynamic?
thanks if anyone can help.

If the api is always going to return an object with than single attribute, you can do something like this:
res = {"USD_GBP":{"val":0.73897}};
res[Object.keys(res)[0]].val
Not the nicest, but it works.

Related

multiple url get async await axios VUE.JS

Probably this is a very stupid question, i'm new in vue.js and javascript, so please forgive me if the question is not properly explained or the answer is simple... I have a problem I wanted to get from two different api and then display it for.
async mounted() {
const { data } = await this.axios.get(
"http://some-ip/api/get"
).then(response => {
this.items = response.data.data.items
})
;
const { data2 } = await this.axios.get(
"http://some-ip/api2/get"
).then(response => {
this.items2 = response.data.data.items
})
;
First api works perfectly, the second no works...
Any good soul who can help this newbie? (if can explain the why of the solution as well, for understand, will be amazing!!)
Thanks in advance!!
It seems like you're trying to destructure data2 from Axios response which doesn't exist on that object, only data does. You have to use data to get the actual response data.
Axios response schema for reference: https://axios-http.com/docs/res_schema
Consider this example as it destructures the data props but sets the name to data2:
const { data: data2 } = await this.axios.get(
"http://some-ip/api2/get"
).then(response => {
this.items2 = response.data.data.items
})
;

Use GET to return records based on nested fields

I am trying to retrieve records based on a value in a mongo dataset that is in a nested object.
data is an object and documentId is a field within it and I want to retrieve just the objects within data that have the documentId of "5da713edf0a1645ae95b11oo"
I tried this code
const res = await axios.get('/api/card',{
params:{
data:documentId: "5da713edf0a1645ae95b11oo"
}
});
but it just returns all the records
Try one of these:
const res = await axios.get('/api/card',{
params:{
documentId: "5da713edf0a1645ae95b11oo"
}
});
This would be a GET request to /api/card?documentId=5da713edf0a1645ae95b11oo
or
const res = await axios.get('/api/card',{
params:{
data: {
documentId: "5da713edf0a1645ae95b11oo"
}
}
});
This would be a GET request to something like /api/card?data=%7B%22documentId%22%3A%225da713edf0a1645ae95b11oo%22%7D
...where %7B%22documentId%22%3A%225da713edf0a1645ae95b11oo%22%7D is URL encoded version of {"documentId":"5da713edf0a1645ae95b11oo"}
according to the documentations it says that we can not do what you have done.
axios.get('/api/card')
.then((res) => {
const data = res.data.id;
//handle your response here.
//can write your logic to retrieve your specific data
});
for further in formations refer this doc
I'm going to assume the data you're receiving on the response is an array of objects. You can filter through it. You're going to have to loop through the data though.
const res = await axios.get('/api/card')
const filteredData = res.data.filter((item) => item.documentId === '5da713edf0a1645ae95b11oo')
You can try this:
data_get() {
axios.get('/api/card')
.then((res) => {
this.setState({
documentId: res.data.id, //5da713edf0a1645ae95b11oo
});
});
}

Streaming JSON data to React results in unexpected end of JSON inpit

I'm trying to stream a lot of data from a NodeJS server that fetches the data from Mongo and sends it to React. Since it's quite a lot of data, I've decided to stream it from the server and display it in React as soon as it comes in. Here's a slightly simplified version of what I've got on the server:
const getQuery = async (req, res) => {
const { body } = req;
const query = mongoQueries.buildFindQuery(body);
res.set({ 'Content-Type': 'application/octet-stream' });
Log.find(query).cursor()
.on('data', (doc) => {
console.log(doc);
const data = JSON.stringify(result);
res.write(`${data}\r\n`);
}
})
.on('end', () => {
console.log('Data retrieved.');
res.end();
});
};
Here's the React part:
fetch(url, { // this fetch fires the getQuery function on the backend
method: "POST",
body: JSON.stringify(object),
headers: {
"Content-Type": "application/json",
}
})
.then(response => {
const reader = response.body.getReader();
const decoder = new TextDecoder();
const pump = () =>
reader.read().then(({ done, value }) => {
if (done) return this.postEndHandler();
console.log(value.length); // !!!
const decoded = decoder.decode(value);
this.display(decoded);
return pump();
});
return pump();
})
.catch(err => {
console.error(err);
toast.error(err.message);
});
}
display(chunk) {
const { data } = this.state;
try {
const parsedChunk = chunk.split('\r\n').slice(0, -1);
parsedChunk.forEach(e => data.push(JSON.parse(e)));
return this.setState({data});
} catch (err) {
throw err;
}
}
It's a 50/50 whether it completes with no issues or fails at React's side of things. When it fails, it's always because of an incomplete JSON object in parsedChunk.forEach. I did some digging and it turns out that every time it fails, the console.log that I marked with 3 exclamation marks shows 65536. I'm 100% certain it's got something to do with my streams implementation and I'm not queuing the chunks correctly but I'm not sure whether I should be fixing it client or server side. Any help would be greatly appreciated.
Instead of implementing your own NDJSON-like streaming JSON protocol which you are basically doing here (with all of the pitfalls of dividing the stream into chunks and packets which is not always under your control), you can take a look at some of the existing tools that are created to do what you need, e.g.:
http://oboejs.com/
http://ndjson.org/
https://www.npmjs.com/package/stream-json
https://www.npmjs.com/package/JSONStream
https://www.npmjs.com/package/clarinet

How do I pass a react DOM state's information to backend(NodeJS) when a button is invoked?

I'm using his logic on the frontend, but I'm having some trouble actually receiving that data on the backend. I'm using the Sails.js framework. Any suggestions?
handleSubmit = () => {
// Gathering together the data you want to send to API
const payload = {
subject: this.state.subject,
message: this.state.message,
};
this.handleAjaxRequest(payload);
};
// Method to send data to the backend
// Making the req -I'm using Axios here.
handleAjaxRequest = (payload) => {
let request = axios({
method: 'post',
url: '/api/',
data: payload,
headers: 'Content-Type: application/json'
});
// Do stuff with the response from your backend.
request.then(response => {
console.debug(response.data);
})
.catch(error => {
console.error(error);
})
};
I used to do this using Express and didn't have these problems.
Any help, method, a suggestion is more than welcome :)
Please forgive my ignorance, I'm just here to learn.
Okay, so the first thing I had to do is generate a new restful API using the command sails generate api data. In the package.json file I set up a proxy that includes the backends endpoint, like this "proxy": "http://localhost:1337" - I mean, you don't need to do this, but if you don't then you have to include this URL part on every request. Because it doesn't change, it's pretty convenient to do so.
On the frontend, I made a function sendData() that takes the necessary data from my previous component (depending on what the user selected) and send that data using axios to the backend -->
sendData = () => {
const { relYear } = this.props.history.location.state.dev;
const { relMonth } = this.props.history.location.state.dev;
const selectedMonth = moment().month(relMonth).format("MM");
const finalSelect = parseInt(relYear + selectedMonth, 10);
axios.post('/data', { 'selectedDate' : finalSelect })
.then(res => console.log('Data send'))
.catch(err => console.error(err));
}
On the backend I fetched the data, did the calculations and send back the result to the frontend of my app. -->
getApiData = () => {
let apiData = [];
axios.get('/data')
.then(res => {
let first = Object.values(res.data.pop()).shift(); // Getting the relevant 'selectedDate'
apiData.push(first);
}).catch(err => console.error(err));
return apiData;
}

How/where to convert dates from the server in a redux app?

I'm starting to study redux now. I used the real-word example as a starting point, using normalizr and reselect to handle data.
Now, I need to understand where is the best place to convert dates coming from the server into js Date objects. Since normalizr already takes care of "some Schemas" I thought it could do that too, but I did not find it there.
Where should I convert these dates? My assumption is that I have to keep those dates already converted on the store. Is that right?
Normalizr can do this - in the current version (v3.3.0) you can achieve it like this:
import { schema } from 'normalizr';
const ReleaseSchema = new schema.Entity('releases', {}, {
processStrategy: (obj, parent, key) => {
return {
...obj,
createdAt: new Date(obj.createdAt),
updatedAt: new Date(obj.updatedAt),
};
},
});
I added a third parameter to callApi (inside api middleware):
function callApi(endpoint, schema, conversionFromServer) {
const fullUrl = (endpoint.indexOf(API_ROOT) === -1) ? API_ROOT + endpoint : endpoint
return fetch(fullUrl)
.then(response =>
response.json().then(json => ({ json, response }))
).then(({ json, response }) => {
if (!response.ok) {
return Promise.reject(json)
}
const camelizedJson = camelizeKeys(json)
const nextPageUrl = getNextPageUrl(response)
let convJson = camelizedJson;
if(conversionFromServer) {
convJson = conversionFromServer(convJson);
}
return Object.assign({},
normalize(convJson, schema),
{ nextPageUrl }
)
})
}
and now I can call it like this:
return {
[CALL_API]: {
types: [ TIMESLOTS_REQUEST, TIMESLOTS_SUCCESS, TIMESLOTS_FAILURE ],
endpoint: `conference/${conferenceId}/timeslots`,
schema: Schemas.TIMESLOT_ARRAY,
conversionFromServer: (data) => {
data.timeslots.forEach((t)=>{
t.startTime=php2js.date(t.startTime)
t.endTime=php2js.date(t.endTime)
});
return data;
}
}
}
This way I keep this conversion "as close to the server" as I can.

Categories