我正在根据来自 API 的两个不同请求构建一个对象。在任何给定时间,这些请求都使用三种不同的 ids
。例如const ids = [1, 2, 3]
整个代码都在 useEffect 中,因为我希望它在每次 ids
更改时都运行。不确定这是否会影响代码执行顺序。
我希望我的程序按以下顺序运行:
我很欣赏这应该处理异步请求,根据其他帖子,某些类型的循环似乎不适合于此。我不确定是使用 async await
还是简单地将 then()
一个接一个地链接起来。
代码类似:
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.
答案 0 :(得分:2)
在 foreach 中使用异步代码有点棘手。您可以改用 for in
并在外部函数之前添加异步
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])
答案 1 :(得分:1)
Hugh 的回答是最好的解决方案,但我会添加其他信息:
另一种方法是使用 Promises 返回来控制主流程。
(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!
})();
这个例子不是使用 Promise 的最优雅的方式,但它很好地展示了它们是如何工作的 =)