Reputation: 15
I am trying to get the fetchIDFromPerson
function to return and assign the returned value to ID
before the rest of the fetchPersons
function executes. It is only returning undefined since it's async. What can I do to get it to work?
Thanks.
const fetchIDFromPerson = name => {
axios
.get(`https://swapi.co/api/people/?search=${name}&format=json`)
.then(response => extractImgIDFromURL(response.data.results[0].url))
.catch(error => console.error(error));
};
let body;
const fetchPersons = (query, imgID) => {
SWAPIGraphQL.post("", { query })
.then(result => {
const { allPersons } = result.data.data;
return (body = allPersons.map(person => {
const ID = fetchIDFromPerson(person.name); //This returns undefined!
return {
...person,
imgID: ID //needs to be assigned a value from fetchIDFromPerson
};
}));
})
.catch(error => console.error(error));
};
fetchPersons(GET_PERSONS_DATA);
Upvotes: 1
Views: 62
Reputation: 707318
You need to make a number of changes to properly use the promises that your asynchronous code return:
return
the axios promise to the caller in fetchIDFromPerson()
..catch()
after logging it so the caller sees the errorreturn
the return SWAPIGraphQL.post()
promise to the caller in fetchPersons()
.body
variable. You don't want side effect programming, particular with asynchronous code. Communicate back results through returned promises.Promise.all()
on the results of the .map()
so you know when all those promises are done.fetchPersons()
use the returned promise to get the resolved value..map()
return the promise from fetchIDFromPerson()
..then()
to where you call fetchIDFromPerson()
where you can return the combined data structure with person and ID in it.response.data.results[0].url
to response.results[0].url
to match the data structure you're getting back.Here's the fixed up code:
const fetchIDFromPerson = name => {
return axios
.get(`https://swapi.co/api/people/?search=${name}&format=json`)
.then(response => extractImgIDFromURL(response.results[0].url))
.catch(error => {
// log and rethrow
console.error(error);
throw error;
});
};
const fetchPersons = (query, imgID) => {
return SWAPIGraphQL.post("", { query })
.then(result => {
const { allPersons } = result.data.data;
return Promise.all(allPersons.map(person => {
return fetchIDFromPerson(person.name).then(ID => {
return {
...person,
imgID: ID
};
});
}));
})
.catch(error => {
// log error and rethrow
console.error(error);
throw error;
});
};
fetchPersons(GET_PERSONS_DATA).then(results => {
console.log(results);
}).catch(err => {
console.log(err);
});
You can simplify fetchPersons()
a bit by using async/await
and not logging the error as many separate places:
const fetchPersons = async (query, imgID) => {
const result = await SWAPIGraphQL.post("", { query });
const { allPersons } = result.data.data;
return Promise.all(allPersons.map(async (person) => {
const ID = await fetchIDFromPerson(person.name);
return {
...person,
imgID: ID
};
}));
};
Upvotes: 1