having trouble chaining multiple axios request - javascript

Ok, so what I am trying to do is do an axios.get() request pull specific data an id specifically, then use that id that I got to put it as a string literal so I can do my second request. I keep getting Info is not defined.
axios
.get(
`https://na1.api.riotgames.com/lol/summoner/v4/summoners/by-name/bloodstrive?api_key=${api}`
)
.then(response => {
info = response.data.id;
})
.then(
axios.get(
`https://na1.api.riotgames.com/lol/league/v4/entries/by-summoner/${info}?api_key=${api}`
)
)
.then(response => {
summoner = response.data;
return summoner;
});
let getSummonerId = (req, res) => {
res.status(200).send(summoner);
};
module.exports = {
getSummonerId
};

Fix your chaining:
axios
.get(
`https://na1.api.riotgames.com/lol/summoner/v4/summoners/by-name/bloodstrive?api_key=${api}`
)
.then(response => {
return response.data.id;
})
.then(info => {
return axios.get(
`https://na1.api.riotgames.com/lol/league/v4/entries/by-summoner/${info}?api_key=${api}`
)
})
.then(response => {
summoner = response.data;
return summoner;
});
Personally, I recommend async for tasks such as this. Makes handling things a lot easier with promises:
let fetchSummoner = async() => {
const res = await axios.get(`https://na1.api.riotgames.com/lol/summoner/v4/summoners/by-name/bloodstrive?api_key=${api}`);
const info = res.data.id;
const res2 = await axios.get(`https://na1.api.riotgames.com/lol/league/v4/entries/by-summoner/${info}?api_key=${api}`);
const summoner = res2.data;
return summoner;
}

In the current code you haven't added a return statement in the 2nd axios request. Failing to this will not fetch and return the 2nd url.
Please try the below code.
axios
.get(
`https://na1.api.riotgames.com/lol/summoner/v4/summoners/by-name/bloodstrive?api_key=${api}`
)
.then(response => {
return response.data.id;
})
.then(info => {
return axios.get(
`https://na1.api.riotgames.com/lol/league/v4/entries/by-summoner/${info}?api_key=${api}`
)
})
.then(response => {
summoner = response.data;
return summoner;
});

Related

how to resolve failed to load response data: No data found for resource with given identifier

POSTING API
export const resendInvitation = async (userName) => { await API.post( 'delta-api',user-mgmt/users/${userName}/resendInvitation, {} ); };
const handleResendInvitation = async () => { await resendInvitation(userName) .then((response) => { setOpen(false); }) .catch((e) => { setOpenNotification(true); setNotificationMessage(e.response.data.message); }); };
help me to get the response data

Get http response status code after response.json()

I would like to get http status code after response.json to use it in my logic later, can I do something with it?
function apiRequest(path, options) {
fetch("api/" + path, options)
.then(response => response.json())
.then(data => {
let res = {
code: 200 //I want to put http status code here,
data: data
}
return res;
})
}
This is slightly tricky using then (as you are currently doing) because you want to get data directly from the response (which is a promise) and some more data from the parsed body (which is another promise).
So you can wrap the status and the data promise in a Promise.all and return that from the first then:
const apiRequest = () => {
const url = "//swapi.dev/api/planets/1/";
fetch(url)
.then((response) => Promise.all([response.status, response.json()]))
.then(([status, data]) => console.log({status, data}))
}
… but it would be easier to use async/await syntax and ditch the callbacks and you then only have to worry about a single function (and therefore scope) rather than multiple.
const apiRequest = async () => {
const url = "//swapi.dev/api/planets/1/";
const response = await fetch(url);
const data = await response.json();
const status = response.status;
console.log({status, data})
}
As an alternative you could consider async/await. That way you have access to response and data at the same time more easily.
async function apiRequest(path, options) {
const response = await fetch("api/" + path, options)
const data = await response.json()
let res = {
code: response.status,
data: data
}
// Do something with res
}
Try this
function apiRequest(path, options) {
fetch("api/" + path, options)
.then(response => Promise.all([Promise.resolve(response.status), response.json()]))
.then(([status, data]) => {
let res = {
code: status //I want to put http status code here,
data: data
}
return res;
})
}
you can git it in the first then before you return response.json something like this
function apiRequest(path, options) {
fetch("api/")
.then((response) => {
let status = response.status;
console.log("status", status);
return response.json();
})
.then((data) => {
console.log(data);
});
}
apiRequest();

How can I "encapsulate" this code into a module so it could become reusable?

I have got this Node.JS snippet and would like to write it as a module, so I can use recaptcha in different parts of my system.
This is how it currently looks like:
app.post('/register_user', (req, res) => {
const secret_key = process.env.RECAPTCHA_SECRET;
const token = req.body.recaptcha;
const url = `https://www.google.com/recaptcha/api/siteverify?secret=${secret_key}&response=${token}`;
fetch(url, { method: "post",})
.then((response) => response.json())
.then((google_response) => {
if (google_response.success == true) {
res.format({'text/html': () => res.redirect(303, '/register'),})
} else {
return res.send({ response: "Failed" });
}
})
.catch((error) => {
return res.json({ error });
});
})
I have tried to write the following module which works absolutely great, but I have absolute no idea about how to call it from the app.post, since I always get undefined as return:
import fetch from 'node-fetch';
export function fetch_out(url, timeout = 7000) {
return Promise.race([
fetch(url),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('timeout')), timeout)
)
]);
}
export async function checkRecaptcha(token, secret_key){
const url = "https://www.google.com/recaptcha/api/siteverify?secret=" + secret_key + "&response=" + token;
try{
const response = await fetch_out(url, 1000);
const google_response = await response.json();
}catch(error){
return error;
}
return google_response;
}
Any help would be appreciated! Thanks!
You could make this method reusable by removing the framework actions that need to happen and only return if the validation was successful or not. This way, it will be reusable in another project that doesn't use a specific framework.
Example module;
export async function checkRecaptcha(token, secret_key) {
const url = `https://www.google.com/recaptcha/api/siteverify?secret=${secret_key}&response=${token}`;
const response = await fetch(url, { method: "post",});
if (!response.ok) return false;
const json = await response.json();
if (!json.success) return false;
return true;
}
Usage:
import { checkRecaptcha } from "./some-file-name";
app.post('/register_user', async (req, res) => {
const isHuman = await checkRecaptcha(req.body.recaptcha, process.env.RECAPTCHA_SECRET);
if (!isHuman) {
return res.send({ response: "Failed" });
}
return res.format({'text/html': () => res.redirect(303, '/register'),});
});
If you specifically want to call an action after the validation, you can also use successful and error callbacks.

How to call multiple fetch APIs

I have to make a fetch call at a url and after getting its response I want to use those results to call another fetch. I have following code:-
async function getDate(request) {
let data;
console.log('handle request called')
await fetch('<first-url>')
.then(res => {
let urls = res.json()
console.log('urls are ', urls)
return urls.data
})
.then((urls) => {
let url = urls[0]
console.log('url is ', url)
return fetch(url)
})
.then((res) => {
data = res.body
})
.catch(() => {
console.log("something went wrong")
})
return new Response(data, {
headers: { 'content-type': 'text/html' },
})
}
I followed the above method after following this tutorial. However it does not seem to work and I am getting urls are {Promise:[Pending]}.
Here issue with return res.json(). res.json() is promisable object, so u have to resolve it to get data.
For your example:
const fetch = require("node-fetch");
async function getDate() {
let data;
console.log("handle request called");
return await fetch('<first-url>')
.then((res) => res.json())
.then((urls) => {
console.log("urls are ", urls);
if (urls.length)
return Promise.all(urls.map((url) => fetch(url).then((x) => x.json())));
return [];
})
.then((responses) => {
console.log("urls are ", responses);
return responses;
});
}
getDate().then(console.log);
Sample:
async function getDate() {
let data;
console.log("handle request called");
return await fetch("https://api.covid19api.com/countries")
.then((res) => res.json())
.then((urls) => {
console.log("urls are ", urls);
return urls;
});
}
getDate().then(console.log);

Refactoring how react/node handles response

I'm using a react frontend and fetching data from my node server. I feel like my code looks a bit redundant, is there a better way to refactor all this?
App.js
searchStock = async (value) => {
let priceURL = `/stock/${ value }/price`
// fetch price data
fetch(priceURL)
.then(res => {
if (res.ok) {
res.json()
.then( (result) => {
this.setState({
price: result
})
})
}
else {
console.log("Something went wrong...")
}
})
}
server.js
app.get('/stock/:symbol/price', (req, res) => {
const token = 'abcde123'
const symbol = req.params.symbol
const apiURL = `https://sandbox.iexapis.com/stable/stock/${symbol}/price?token=T${token}`
fetch(apiURL)
.then(response => {
console.log(response.status)
if (response.ok) {
response.json().then((data) => {
res.json(data)
});
}
else {
res.sendStatus(response.status)
}
})
.catch(error => {
console.log(error);
});
})
As these two code segments live in different apps (frontend and backend) I don't think there's a pretty way of DRYing this.
Introduce library file with fetching logic
src/helper.js
exports.fetchHelper = (url) => fetch(url)
.then(response => {
if (response.ok) {
return response.json();
} else {
res.sendStatus(response.status)
}
})
.catch(console.error);
and use respectively
app.js
import { fetchHelper } from 'src/helper'; // or whatever else your bundler setup requires
searchStock = async (value) => {
const priceURL = `/stock/${ value }/price`;
await fetchHelper(priceURL).then((result) => {
this.setState({
price: result
})
})
}
server.js
const fetchHelper = require('src/helper').fetchHelper;
app.get('/stock/:symbol/price', (req, res) => {
const token = 'abcde123'
const symbol = req.params.symbol
const apiURL = `https://sandbox.iexapis.com/stable/stock/${symbol}/price?token=T${token}`
fetchHelper(apiURL).then((response) => {
res.json(data);
})
Or something similar...

Categories