JS/React - 我应该如何在 for 循环中使用 fetch 调用?
JS/React - How should I use a fetch call inside of a for loop?
除了最简单的形式,我对异步函数还有点不熟悉,所以我希望这里有人能帮助我。
一些信息:
getCollection() returns 对象数组,如下所示。
{
"id": 1,
"userId": 3,
"gameId": 3498,
"review": "Testing review for game 1"
},
getGameById() 从外部 API.
接收一个整数(游戏 ID)和 returns 该游戏对象
gameArray 应该填充游戏对象,这些对象在外部 API 中的 ID 与 getCollection 提供的对象数组中的 ID 相匹配。
const [games, setGames] = useState([])
const getGames = () => {
getCollection().then(userGames => {
let gameArray = []
for (const eachObj of userGames) {
if (eachObj.userId === currentUserId) {
getGameById(eachObj.gameId).then(game => {
gameArray.push(game)
})
}
}
Promise.all(gameArray).then(() => {
console.log(gameArray) //logs empty array, but shouldn't be empty
setGames(gameArray)
})
})
}
我以前从未使用过 Promise.all,这只是我认为可以解决我遇到的这个问题的方法。
您传递给 Promise.all
的数组需要包含承诺,但您正在推送游戏对象 - 而且您是异步执行的,因此当您将它传递给时数组仍然是空的Promise.all
.
const getGames = () => {
getCollection().then(userGames => {
let gamePromises = []
for (const eachObj of userGames) {
if (eachObj.userId === currentUserId) {
gamePromises.push(getGameById(eachObj.gameId))
// ^^^^^^^^^^^^^^^^^^ ^
}
}
return Promise.all(gamePromises)
// ^^^^^^ chaining
}).then(gameArray => {
// ^^^^^^^^^
console.log(gameArray)
setGames(gameArray)
})
}
简化:
async function getGames() {
const userGames = await getCollection()
const gamePromises = userGames
.filter(eachObj => eachObj.userId === currentUserId)
.map(eachObj => getGameById(eachObj.gameId))
const gameArray = await Promise.all(gamePromises)
console.log(gameArray)
setGames(gameArray)
}
Promise.all
采用一系列承诺。
首先,您必须构建承诺数组。然后你必须用这个数组调用 Promise.all
来检索所有游戏:
function getGames() {
getCollection().then(userGames => {
const gamePromises = userGames
.filter(userGame => userGame.userId == currenUserId)
.map(userGame => getGameById(userGame.gameId));
Promise.all(gamePromises).then(games=> {
console.log(games);
setGames(games)
});
})
}
这是另一个使用 async function
的解决方案,它可能更具可读性
async function getGames() {
const userGames = await getCollection();
const currentUserGames = userGames.filter(({userId}) => userId == currentUserId);
const games = await Promise.all(userGames.map(({gameId}) => getGameById(gameId));
setGames(games);
}
除了最简单的形式,我对异步函数还有点不熟悉,所以我希望这里有人能帮助我。
一些信息:
getCollection() returns 对象数组,如下所示。
{
"id": 1,
"userId": 3,
"gameId": 3498,
"review": "Testing review for game 1"
},
getGameById() 从外部 API.
接收一个整数(游戏 ID)和 returns 该游戏对象gameArray 应该填充游戏对象,这些对象在外部 API 中的 ID 与 getCollection 提供的对象数组中的 ID 相匹配。
const [games, setGames] = useState([])
const getGames = () => {
getCollection().then(userGames => {
let gameArray = []
for (const eachObj of userGames) {
if (eachObj.userId === currentUserId) {
getGameById(eachObj.gameId).then(game => {
gameArray.push(game)
})
}
}
Promise.all(gameArray).then(() => {
console.log(gameArray) //logs empty array, but shouldn't be empty
setGames(gameArray)
})
})
}
我以前从未使用过 Promise.all,这只是我认为可以解决我遇到的这个问题的方法。
您传递给 Promise.all
的数组需要包含承诺,但您正在推送游戏对象 - 而且您是异步执行的,因此当您将它传递给时数组仍然是空的Promise.all
.
const getGames = () => {
getCollection().then(userGames => {
let gamePromises = []
for (const eachObj of userGames) {
if (eachObj.userId === currentUserId) {
gamePromises.push(getGameById(eachObj.gameId))
// ^^^^^^^^^^^^^^^^^^ ^
}
}
return Promise.all(gamePromises)
// ^^^^^^ chaining
}).then(gameArray => {
// ^^^^^^^^^
console.log(gameArray)
setGames(gameArray)
})
}
简化:
async function getGames() {
const userGames = await getCollection()
const gamePromises = userGames
.filter(eachObj => eachObj.userId === currentUserId)
.map(eachObj => getGameById(eachObj.gameId))
const gameArray = await Promise.all(gamePromises)
console.log(gameArray)
setGames(gameArray)
}
Promise.all
采用一系列承诺。
首先,您必须构建承诺数组。然后你必须用这个数组调用 Promise.all
来检索所有游戏:
function getGames() {
getCollection().then(userGames => {
const gamePromises = userGames
.filter(userGame => userGame.userId == currenUserId)
.map(userGame => getGameById(userGame.gameId));
Promise.all(gamePromises).then(games=> {
console.log(games);
setGames(games)
});
})
}
这是另一个使用 async function
的解决方案,它可能更具可读性
async function getGames() {
const userGames = await getCollection();
const currentUserGames = userGames.filter(({userId}) => userId == currentUserId);
const games = await Promise.all(userGames.map(({gameId}) => getGameById(gameId));
setGames(games);
}