gpt4 book ai didi

javascript - 如何从 Array.map() 函数正确返回异步数据

转载 作者:行者123 更新时间:2023-12-02 23:09:20 24 4
gpt4 key购买 nike

我正在开发一个小型网络应用程序来跟踪本地棋盘游戏组的积分。记分板将跟踪玩家玩的总游戏数、获得的总积分以及游戏中每个可用派系的玩游戏数和获得的积分的明细。

我目前正碰壁,试图为/players/withFactions/创建 Node/快速端点,它将返回聚合玩家数据以及每个派系的分割。

正如您将在所附代码中看到的,逻辑工作正常,并且第一个 console.log 位置的数据正确。该数据只是返回,我将返回记录在第二个控制台日志中,其中数据似乎已更改。变异数据似乎总是采用第一个 console.log 位置最后返回的元素的形式。我希望在审查代码后这会更有意义。

我确信我的问题在于我如何处理所有异步,但我无法找出解决方案。

我用多种不同的方式解决了这个问题:回调、 promise 、异步/等待。一切都具有相同的结果。数据似乎在返回前端之前就在我身上发生了变化。

router.get('/withFactions', async (req, res) => {

const { rows: players } = await db.query('SELECT * FROM players');
const { rows: factions } = await db.query('SELECT * FROM factions');

const playerResults = await Promise.all(players.map( async (player) => {
await db.query('SELECT * FROM gameentry WHERE player_id = $1', [player.id]).then((result) => {
const gameEntries = result.rows;
const factionTotals = factions.map((faction) => {
const factionEntries = gameEntries.filter(game => game.faction_id === faction.id)
faction.totalPoints = factionEntries.reduce((acc, curr) => {
return acc + curr.points;
}, 0)
return faction;

})
player.factionTotals = factionTotals;
})
player.factionTotals.forEach(element => console.log(element.totalPoints))

// total scores are recording correctly here 4,0,0 5,0,3 0,5,0 (from DB data)

return await player;
}))

await playerResults.forEach(player => player.factionTotals.forEach(element => console.log(element.totalPoints)));

// total scores are wrong here. Each set is 0,5,0. Seems to just replicate the last set from within the promise

res.send(await playerResults);
})

注意:唯一不正确的数据是player.factionTotals,其余的玩家数据仍然准确。

我确信那里还有一些不必要的等待。我已经关注这个问题太久了。我希望我能在这方面得到一些帮助。

最佳答案

Jaromanda X 所示问题是您修改了每个玩家的派系,因此只有最后的修改才会“保留”。

一般来说,我建议在使用 map 时不要产生副作用,并且只返回新对象或未修改的对象。为此,您应该能够将代码修改为如下所示:

router.get('/withFactions', async (req, res) =>
{
const { rows: players } = await db.query('SELECT * FROM players');
const { rows: factions } = await db.query('SELECT * FROM factions');

const playerResults = await Promise.all(players.map(async player =>
{
const { rows: gameEntries } = await db.query('SELECT * FROM gameentry WHERE player_id = $1', [player.id]);

const factionTotals = factions.map(faction =>
{
const factionEntries = gameEntries.filter(game => game.faction_id === faction.id)
var totalPoints = factionEntries.reduce((acc, curr) => acc + curr.points, 0);

return { ...faction, totalPoints }; // Copies faction properties instead of modifying
})

const extendedPlayer = { ...player, factionTotals };

extendedPlayer.factionTotals.forEach(element => console.log(element.totalPoints))

return extendedPlayer;
}))

playerResults.forEach(player => player.factionTotals.forEach(element => console.log(element.totalPoints)));

res.send(playerResults);
})

使用展开 (...) 会复制属性,因此每个玩家迭代的原始 factions 列表都是相同的。用于创建 extendedPlayer 的第二个扩展对于防止您的问题可能不是绝对必要的,但也可以保持外部 map 的纯净。

关于javascript - 如何从 Array.map() 函数正确返回异步数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57446933/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com