- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发一个小型网络应用程序来跟踪本地棋盘游戏组的积分。记分板将跟踪玩家玩的总游戏数、获得的总积分以及游戏中每个可用派系的玩游戏数和获得的积分的明细。
我目前正碰壁,试图为/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/
我是一名优秀的程序员,十分优秀!