NodeJS, ожидание работы с БД
Мне нужно добиться того, чтобы ответ от бекенда на фронт приходил только после того, как закончится добавление данных в БД. После получения ответа, фронт посылает запрос в БД (и там должна быть эта информация).
Ни один из кучи вариантов с Промисами не помог, судя по всему, я что-то делаю не так.
Нужно добиться того, чтобы res.send срабатывал только после того, как выполнится добавление данных в БД в модуле bruteForceMatches
router.post('/summoner', async (req, res) => {
const name = encodeURI(req.body.summoner);
const region = (req.body.region).toUpperCase();
const profileURL = `https://${region}.api.riotgames.com/lol/summoner/v4/summoners/by-name/${name}`;
const summonerInfo = await getData(profileURL, collectSummonerInfo, region);
const leagueURL = `https://${region}.api.riotgames.com/lol/league/v4/entries/by-summoner/${summonerInfo.sumId}`;
const rankedInfo = await getData(leagueURL, collectRankedInfo);
const puuId = summonerInfo.puuId;
const matchList = [];
let start = 0;
const matchListURL = `https://europe.api.riotgames.com/lol/match/v5/matches/by-puuid/${puuId}/ids?start=${start}&count=5`;
matchList.push(...await getData(matchListURL));
const result = await bruteForceMatches(matchList);
if (result === 'hey') {
console.log(4, result);
res.send(JSON.stringify({...summonerInfo, ...rankedInfo}));
}
})
Так выглядит модуль bruteForceMatches
module.exports = async (matchList) => {
const answers = [];
const func = () => {
return new Promise((resolve, reject) => {
for (let matchId of matchList) {
match.findOne({matchId: matchId}, async (err, doc) => {
if (!doc) {
const matchURL = `https://europe.api.riotgames.com/lol/match/v5/matches/${matchId}`;
const matchInfo = await getData(matchURL);
const timelineURL = `https://europe.api.riotgames.com/lol/match/v5/matches/${matchId}/timeline`;
const timeline = await getData(timelineURL);
if (Object.keys(matchInfo).length !== 0) {
const allowedTypeIds = [400, 420, 440];
const typeId = matchInfo.info.queueId;
const timelineInfo = collectTimelineInfo(timeline);
pushMatchInDB(matchInfo, timelineInfo);
if (allowedTypeIds.includes(typeId)) {
const result = await pushInfoInDB(matchInfo.info);
if (result === 'hey') {
resolve(matchId);
}
}
}
}
})
}
})
}
answers.push(func());
const res = await Promise.all(answers).then((answers) => {
console.log(answers);
return 'hey';
})
if (res === 'hey') {
console.log(3, res);
return res;
}
}
А так модуль pushInfoInDB. Именно в этом модуле происходит непосредственное добавление данных БД.
module.exports = async (obj) => {
const answers = [];
const func = () => {
return new Promise((resolve, reject) => {
for (let key in obj) {
const {sumId, sumName, win, solo, flex, normal} = obj[key];
const {champName, champId, kills, deaths, assists, physical, magic, trueDmg, restore, shield, cs, gold, vision, wards} = obj[key].champion;
const {date, matchType, dmgTaken, CC, killingSpree, double, triple, quadra, penta} = obj[key].champion;
const role = (obj[key].role).toLowerCase();
const dmg = physical + magic + trueDmg;
const heal = restore + shield;
const kda = calcRatio((kills + assists), deaths);
const records = {kda, kills, deaths, assists, dmg, heal, cs, gold, vision, wards, dmgTaken, CC, killingSpree, double, triple, quadra, penta};
let type = '';
if (solo) type = 'solo';
if (flex) type = 'flex';
if (normal) type = 'normal';
summoner.updateOne({sumId: sumId}, {...}, {upsert: true}, (error, writeOpResult) => answers.push(resolve(sumId)));
for (let key in records) {
const value = records[key];
summoner.updateOne({sumId: sumId, [`records.${key}.value`]: {$lt: value}}, {...});
}
}
resolve(1);
})
}
answers.push(func());
const res = await Promise.all(answers).then((answers) => {
console.log(answers);
return 'hey';
})
if (res === 'hey') {
console.log(1, res);
return res;
}
}
Помогите, пожалуйста, разобраться с проблемой. Моя благодарность будет безгранична!
Модуль collectTimeLineInfo
module.exports = (obj) => {
if (!obj) return null;
const frames = obj.info.frames;
let participant = {};
for (let i = 1; i <= 10; i++) {
const lvlUp = [], itemPurchase = [];
for (let frame of frames) {
for (let event of frame.events) {
if (event.participantId === i && event.type === "SKILL_LEVEL_UP") {
lvlUp.push({skill: event.skillSlot, time: event.timestamp});
}
if (event.participantId === i && event.type === "ITEM_PURCHASED") {
itemPurchase.push({item: event.itemId, time: event.timestamp});
}
participant[i] = {lvlUp, itemPurchase};
}
}
}
return participant;
}
Ответы (1 шт):
Вообще, я сомневаюсь, что учёл всё (функции getData и pushMatchInDB так и остались за кадром, а в них наверняка много весёлого). Да и проверить попросту не на чем... Короче, попробуйте:
bruteForceMatches
module.exports = async (matchList) => {
const answers = [];
for (const matchId of matchList) {
const doc = await match.findOne({ matchId });
if (doc) {
continue;
}
try {
const matchURL = `https://europe.api.riotgames.com/lol/match/v5/matches/${matchId}`;
const matchInfo = await getData(matchURL);
if (Object.keys(matchInfo).length === 0) {
continue;
}
const timelineURL = `https://europe.api.riotgames.com/lol/match/v5/matches/${matchId}/timeline`;
const timeline = await getData(timelineURL);
const allowedTypeIds = [400, 420, 440];
const typeId = matchInfo.info.queueId;
const timelineInfo = collectTimelineInfo(timeline);
await pushMatchInDB(matchInfo, timelineInfo);
if (allowedTypeIds.includes(typeId) && matchInfo.info) {
await pushInfoInDB(matchInfo.info);
answers.push(matchId);
}
} catch (err) {
console.error(err);
}
}
return answers;
};
pushInfoInDB
module.exports = async (obj) => {
const answers = [];
for (const key in obj) {
try {
const { sumId, sumName, win, solo, flex, normal } = obj[key];
const { champName, champId, kills, deaths, assists, physical, magic, trueDmg, restore, shield, cs, gold, vision, wards } = obj[key].champion;
const { date, matchType, dmgTaken, CC, killingSpree, double, triple, quadra, penta } = obj[key].champion;
const role = (obj[key].role)?.toLowerCase();
const dmg = physical + magic + trueDmg;
const heal = restore + shield;
const kda = calcRatio((kills + assists), deaths);
const records = { kda, kills, deaths, assists, dmg, heal, cs, gold, vision, wards, dmgTaken, CC, killingSpree, double, triple, quadra, penta };
let type = '';
if (solo) type = 'solo';
if (flex) type = 'flex';
if (normal) type = 'normal';
await summoner.updateOne(
{ sumId },
{ /**/ },
{ upsert: true }
);
answers.push(sumId);
for (let key in records) {
const value = records[key];
await summoner.updateOne(
{ sumId: sumId, [`records.${key}.value`]: { $lt: value } },
{ /**/ }
);
}
} catch (err) {
console.error(err);
}
}
return answers;
};