簡體   English   中英

異步 Promise 與 Node.js 和 MongoDB 中的循環鏈接

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM