[英]Async Promise chaining with a loop in Node.js & MongoDB
我最近將我的數據庫從 Sql 服務器導入到 MongoDB,轉換為完整的 MERN 堆棧。 我有一個titles_table、一個skills_table 和一個title_skills_table。 title_skills_table 是一個“連接”表,其中包含技能和標題表的 _id,因為某些技能可以屬於多個標題。
我正在嘗試調用與特定標題相關的所有 title_skills,我已經能夠做到這一點。 我想不通的是如何使用 title_skills 數組響應來通過技能表中的技能 ID 查找所有技能。
我已經嘗試過異步瀑布、異步鏈接等,但它要么只是返回一個空的錯誤消息,要么破壞了服務器。
我可以單獨進行這兩個調用並從每個調用中得到響應,它將它們加入一個循環鏈中,這似乎要了我的命。
這是我目前擁有的:
const router = require('express').Router();
const Skill = require('../models/Skill');
const TitleSkills = require('../models/TitleSkills');
//Get A Skill by Skill Id
router.get("/skill/:id", async (req, res) => {
try {
const skill = await Skill.findOne({skill_id: req.params.id}).populate('SkillCategory')
res.json(skill);
} catch (err) {
res.json({ message: err });
}
});
//Get TitleSkills by TitleId *by itself
// router.get("/title/:id", async (req, res) => {
// try {
// const titleSkills = await TitleSkills.find({title_id: req.params.id})
// res.json(titleSkills)
// } catch (err) {
// res.json({ message: err });
// }
// });
//Get a skill by skill id and through it in an array
const getSkillsByskillId = (id) => new Promise((resolve, reject) => {
const skillsArr = []
router.get(`/skill/${id}`)
.then((result) => resolve(skillsArr.push(result.data)))
return(skillsArr)
.catch(error => reject(error))
});
//Get all TitleSkills by TitleId and loop each TitleSkill through Skills Table
router.get("/title/:id", async (req, res) => {
try {
const titleSkills = await TitleSkills.find({title_id: req.params.id})
.then(titleSkills.forEach((ts) => {
getSkillsByskillId(ts.skill_id)
}))
res.json(titleSkills)
} catch (err) {
res.json({ message: err });
}
});
module.exports = router;
#救救我
這個 promise 鏈格式不正確:
//Get a skill by skill id and through it in an array
const getSkillsByskillId = (id) => new Promise((resolve, reject) => {
const skillsArr = [];
router.get(`/skill/${id}`)
.then((result) => resolve(skillsArr.push(result.data)))
return (skillsArr)
.catch(error => reject(error)); // <- never executed
});
該return (skillsArr)
在router.get
被調用后立即執行,返回一個空數組。
這個修改后的代碼返回一個 promise ,它解析為skillsArr
(不需要包含一個除了reject
之外什么都不做的 catch 塊):
//Get a skill by skill id and return it in an array
const getSkillsByskillId = (id) => {
const skillsArr = [];
return router.get(`/skill/${id}`)
.then((result) => {
skillsArr.push(result.data);
return skillsArr;
});
};
此外,對getSkillsByskillId
的調用忽略了解析:
getSkillsByskillId(ts.skill_id)
}))
這可能應該是這樣的:
getSkillsByskillId(ts.skill_id)
.then(skillsArr => doSomething() );
最后,這個塊不必要地結合了await
和 Promise 鏈。
const titleSkills = await TitleSkills.find({title_id: req.params.id})
.then(titleSkills.forEach((ts) => {
getSkillsByskillId(ts.skill_id);
}))
這是等價的:
const titleSkills = await TitleSkills.find({title_id: req.params.id});
for (let ts of titleSkills) {
const skillsArr = await getSkillsByskillId(ts.skill_id);
// do something with skillsArr
});
這相當於同名的OP function...
const getSkillsByskillId = async (id) => {
const result = await Skill.findOne({skill_id: req.params.id}).populate('SkillCategory')
return result.data; // removed OP's extra wrap of the array
}
從路由中調用它,通過映射它,收集承諾,並與 Promise.all() 一起運行它們...
router.get("/title/:id", async (req, res) => {
try {
const skills = await TitleSkills.find({title_id: req.params.id})
let promises = skills.map(ts => getSkillsByskillId(ts.skill_id));
let titleSkills = await Promise.all(promises);
res.json(titleSkills)
} catch (err) {
res.json({ message: err });
}
});
//Get A skill by skill_id
const getSkillsByskillId = async (id) => {
const result = await Skill.findOne({skill_id: id}).populate('SkillCategory')
return result;
}
//Get all TitleSkills by TitleId and then Map each TitleSkill to Skills_Table
router.get("/title/:id", async (req, res) => {
try {
const titleSkills = await TitleSkills.find({title_id: req.params.id})
let promises = titleSkills.map(ts => getSkillsByskillId(ts.skill_id));
let skills = await Promise.all(promises);
res.json(skills)
} catch (err) {
res.json({ message: err });
}
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.