我正在开展一个项目,我希望其中一个功能可以返回修改后的“播放器”。对象
想象一下,如果你有一个等于的玩家(下面不是真正的代码,但逻辑是相同的):
{
id: 1,
val: 590
}
和stats(对象数组)等于:
[
{
id: 1,
val: 400
}
{
id: 2,
val: 590
}
]
问题在于,当我进行嵌套映射(.map())时,我的播放器以某种方式返回(解析)比map函数结束迭代更快。但是,我希望它只在所有迭代完成后返回。
我尝试了什么:我找到了实现计数的解决方案,并检查它是否等于outter map函数。它既不起作用,因为我的代码发送得太快(在迭代完成之前),或根本没有解决。
我非常感谢听到任何建议,甚至是实践(我应该这样做还是不行),因为我试图解决这个问题将近2天。
这是近似的样子(原始的更复杂):
以下是代码的链接:https://jsfiddle.net/j0ownf0m/
const do_magic_with_measurements = (db, data) => {
let session = data.session;
let player = data.player;
let count = 0;
return new Promise((resolve, reject) => {
session.Measurements.map(measurement => {
player.Stats.map(stat => {
if (measurement.Type === stat.Type) {
/* Update maximum value */
if (measurement.MaxValue === stat.MaxValue) {
db.collection(SESSIONS_COLLECTION)
.find({
PlayerID: ObjectID(session.PlayerID),
"Measurements.Type": measurement.Type
}, {
"Measurements.$": 1
})
.sort({
"Measurements.MaxValue": -1
})
.toArray()
.then(one_session => {
console.log(one_session);
if (one_session[0].Measurements[0].MaxValue == stat.MaxValue) {
// update maximum value if they were equal
stat.MaxValue = 0;
} else {
// otherwise set the next maximum value
stat.MaxValue = one_session[0].Measurements[0].MaxValue;
}
})
.catch(error => {
throw error;
.catch(error => {
throw error;
});
}
}
});
});
count++;
if (count === session.Measurements.length) {
resolve(player);
}
});
};
答案 0 :(得分:0)
如果您可以使用async / await模式,那么您可以通过以下方式更改问题中的代码。这将允许您迭代玩家,一旦您的功能完成,您可以使用更改的玩家数据做一些事情
注意,因为它们是引用,所以它们会在原始数组中进行更改,如果您不想要它,您可以深度克隆数组,并在那里进行更改
请注意,此处提出的代码基于your jsfiddle,并显示了如何使用async / await模式更改它的抽象方式
const mockedData = [
{ player: 1, value: 1000 },
{ player: 2, value: 1500 },
{ player: 3, value: 1900 }
];
const mockedPlayers = [
{ player: 1, value: 1000 },
{ player: 2, value: 1500 },
{ player: 3, value: 1900 }
];
async function findArrayInDb(matchBy, sortBy) {
// here you could create your db call
// and use the arguments for the property filtering
// for now, always the same comes out
return new Promise((resolve, reject) => {
setTimeout(() => resolve( mockedData ), 1000);
});
}
const doDelayedPromisesWork = async (players) => {
for (let i = 0; i < players.length; i++) {
let player = players[i];
let result;
result = await findArrayInDb( player );
if (player.player === result[0].player) {
console.log('found player');
player.value = 0;
} else {
console.log('player was not the first');
player.value += 500;
}
}
// no need to return, the players are reference types so they will be changed inside the for loop
};
const doPlayerMagic = async () => {
console.log('iterating mocked players');
var result = await doDelayedPromisesWork( mockedPlayers );
return new Promise(resolve => resolve());
};
doPlayerMagic().then(() => /*completed iteration of the players*/ console.log('finished'));
// runs before anything happens with the players
console.log('instructions send');
&#13;