У меня маленькая игра с опрокидыванием. После завершения игры я получаю все советы от db mongoose, а затем повторяю эти советы с помощью forEach.
Для каждого из этих советов я получаю имя пользователя и загружаю пользователя из базы данных mongoose, чтобы увеличить баллы этого пользователя, и после этого пользователь сохраняет обратно в базу данных.
Один пользователь может иметь более одного совета.
Tips.find({...}).exec(function(err, gameTips) {
gameTips.forEach(tip, i) => {
User.findOne({
username: tip.username
}).exec(function(err, user) {
user.points = user.points + 1;
user.save(function(err) {
console.log("Points were increased");
});
});
});
}
Теперь моя проблема в том, что findOne пользователя выполняется перед сохранением предыдущей обработки подсказок. Таким образом, очки не будут увеличены правильно.
Пользователь: testUser имеет 4 совета |
Ожидается: testUser.points = 4; |
Текущий: testUser.points = 2;
Есть ли возможность сделать это асинхронно, так что поиск и сохранение для всех пользователей будут выполняться один за другим, чтобы каждый раз, когда я это делал:
user.points = user.points +1;
У меня будут обновленные очки перед увеличением?
EDIT
Спасибо за ваши подсказки. Я попытался принять это, и мой код теперь:
async function updateUserPoints(schedule) {
try {
console.log("Load Schedules");
const scheduleTips = await Tip.find({
scheduleId: schedule._id,
season: schedule.season
});
console.log(scheduleTips);
if (scheduleTips.length) {
for (const scheduleTip of scheduleTips) {
console.log("Load User for scheduleTip: " + scheduleTip.tip);
let user = await User.findOne({
username: scheduleTip.username
})
console.log(user);
if (user) {
const winner = calculateWinner(schedule);
const points = calculatePoints(scheduleTip, winner);
console.log("WINNER: " + winner);
console.log("POINTS: " + points);
user.tippspiel.overallPoints = user.tippspiel.overallPoints + points;
user.tippspiel.seasonPoints = user.tippspiel.seasonPoints + points;
user.tippspiel.gameWeekPoints = user.tippspiel.gameWeekPoints + points;
await user.update({ username: scheduleTip.username }, { $inc: { "tippspiel.overallPoints": points } }, function(err) {
if (err) {
logger.error("[Tippspiel-User]: " + err);
} else {
logger.info("[Tippspiel-User]: User tippspiel points were updated.");
}
});
}
}
}
} catch (err) {
console.error(err);
}
}
function calculateWinner(schedule) {
let winner;
if (schedule.homeScore > schedule.awayScore) {
//Home wins
winner = "home";
} else if (schedule.homeScore < schedule.awayScore) {
//Away wins
winner = "away";
} else if (schedule.homeScore == schedule.awayScore) {
//Tie/Draw
winner = "draw";
}
return winner;
}
function calculatePoints(scheduleTip, winner) {
const POINTS_CORRECT_WINNER = settings.tippspiel.pointsCorrectWinner;
const POINTS_CORRECT_DRAW = settings.tippspiel.pointsCorrectDraw;
//If user has tipped correct
if (scheduleTip.tip === winner) {
let points = 0;
if ((scheduleTip.tip === "home") || (scheduleTip.tip === "away")) {
points = points + POINTS_CORRECT_WINNER;
} else if (scheduleTip.tip === "draw") {
points = points + POINTS_CORRECT_DRAW;
}
return points;
} else {
return 0;
}
}
Сейчас проверю :) 1023 *