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);
}