Reputation: 5083
I am building an object out of two different requests from an API. There are three different ids
used for those requests at any given time. e.g. const ids = [1, 2, 3]
The whole code is inside of a useEffect, as I would like it to run every time the ids
change. Not sure whether this affects or not the code execution order.
I would like my program to behave in this order:
I appreciate this should deal with async requests, and some types of loops don't seem to be appropriate for this according to other posts. I am not sure whether to use async await
or simply chain then()
one after another.
Code is similar to this:
useEffect(() => {
// ... some other code ...
const obj = {}
// 1st loop
ids.forEach(id =>{
fetch(`api/general_info?id=${id}`)
//whatever comes as response, merge into 'obj'
})
// 2nd loop (to be run only after first loop has finished merging into obj)
idsToCompare = [[1, 2], [1, 3], [2, 3]] //
idsToCompare.forEach(([id1, id2]) =>{
fetch(`api/compare/?id1=${id1}&id2=${id2}`)
//whatever comes as response, merge into 'obj'
})
// 3 run this code ONLY AFTER the above loops have finished executing
// (and obj merge is complete)!
setCompleteObjToDisplay(obj) // React's setState
console.log(obj) // complete obj!
}, [ids]) //every time ids change, this code should run.
Upvotes: 0
Views: 714
Reputation: 366
It's a bit tricky to use async code with foreach. You could use for in
instead and add async before the outer function
useEffect(() => {
(async () => {
let obj = {}
for(const id in ids) {
const res = await fetch(...)
obj = {...obj, res}
}
idsToCompare = [[1, 2], [1, 3], [2, 3]]
for(const [id1, id2] in idsToCompare) {
const res = await fetch(...)
obj = {...obj, res}
}
setCompleteObjToDisplay(obj) // I don't know if this function is asynchronous. Is so, add an await statement
console.log(obj)
})(), [dependencies])
Upvotes: 2
Reputation: 253
Hugh's answer is the best solution, but I will add another information:
Another way to do it would be using Promises returns to control the main flow.
(async function() {
const obj = {}
await new Promise ((resolve, reject) => {
// 1st loop
ids.forEach(async (id) => {
let data = await fetch(`api/general_info?id=${id}`)
//whatever comes as response, merge into 'obj'
resolve(data);
})
})
// 2nd loop (to be run only after first loop has finished merging into obj)
idsToCompare = [[1, 2], [1, 3], [2, 3]] //
await new Promise ((resolve, reject) => {
idsToCompare.forEach(([id1, id2]) =>{
let data = await fetch(`api/compare/?id1=${id1}&id2=${id2}`)
resolve(data);
//whatever comes as response, merge into 'obj'
})
})
// 3 run this code ONLY AFTER the above loops have finished executing
// (and obj merge is complete)!
setCompleteObjToDisplay(obj)
console.log(obj) // complete obj!
})();
This example is not the most elegant way to use Promises, but it serves well to show how they work =)
Upvotes: 1