Recientemente importé mi base de datos de Sql Server a MongoDB, convirtiéndola en una pila MERN completa. Tengo una titles_table, una skills_table y una title_skills_table. title_skills_table es una tabla de 'unión' que contiene los _id de las tablas de habilidades y títulos, ya que algunas habilidades pueden tener varios títulos.
Estoy tratando de llamar a todas las title_skills asociadas con un título en particular, lo que he podido hacer. Lo que no puedo entender es cómo usar esa respuesta de matriz title_skills para encontrar todas las habilidades por skill_id en la tabla de habilidades.
Probé la cascada asíncrona, el encadenamiento asíncrono, entre otras cosas, pero solo devuelve un mensaje de error vacío o rompe el servidor.
Puedo hacer las dos llamadas individualmente y obtener una respuesta de cada una, es unirlas en una cadena circular que parece matarme.
Esto es lo que tengo actualmente:
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;#Sálvame
Esta cadena de promesas está mal formada:
//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 }); Ese return (skillsArr) se ejecuta inmediatamente después de llamar a router.get , devolviendo una matriz vacía.
Este código modificado devuelve una promesa que se resuelve en skillsArr (no es necesario incluir un bloque catch que no haga nada más que reject ):
//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; }); }; Además, esta llamada a getSkillsByskillId ignora la resolución:
getSkillsByskillId(ts.skill_id) }))Esto probablemente debería ser algo como esto:
getSkillsByskillId(ts.skill_id) .then(skillsArr => doSomething() ); Finalmente, este bloque está combinando await y Promise chain innecesariamente.
const titleSkills = await TitleSkills.find({title_id: req.params.id}) .then(titleSkills.forEach((ts) => { getSkillsByskillId(ts.skill_id); }))Esto es equivalente:
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 });Esto es equivalente a la función OP del mismo nombre...
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 }Llámelo desde la ruta, mapeándolo, recopilando promesas y ejecutándolas junto con 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 }); } });