![](/img/trans.png)
[英]How to return a value from a async function in array.map in javascript?
[英]How to properly return async data from Array.map() function
我正在开发一个小型Web应用程序,以跟踪本地棋盘游戏小组的积分。 计分板将跟踪玩家参加的总比赛数,获得的总积分以及比赛的细目分类和每个派系中可获得的积分。
我目前正在碰壁,试图为/ players / withFactions /创建节点/ express端点,这将返回聚合的玩家数据以及每个派别的细分。
正如您将在所附的代码中看到的那样,逻辑正确地工作,并且数据在第一个console.log的位置正确。 该数据只是返回了,我将返回值记录在第二个控制台日志中,那里的数据似乎已更改。 突变的数据似乎总是采用第一个console.log位置中最后返回的元素的形式。 我希望这在审查代码时会更有意义。
我确信我的问题在于我如何处理所有异步,但是我无法找出解决方案。
我已经以多种不同的方式攻击了这个问题:回调,承诺,异步/等待。 所有结果都相同。 在返回前端之前,数据似乎在我身上发生了变化。
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所指出的那样 ,问题在于您需要为每个玩家修改factions
,因此只有最后一次修改会“停留”。
通常,我建议使用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);
})
使用spread( ...
)复制属性,因此每个玩家迭代的原始factions
列表都相同。 创建extendedPlayer
的第二步可能不是严格防止您遇到的问题,但也可以使外部map
保持纯净。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.