В Express.js как сделать так, чтобы res.send ожидал получения данных из базы данных - PullRequest
3 голосов
/ 23 мая 2019

Метод res.send() возвращает (пусто) до того, как данные извлекаются из базы данных (Mongodb) из метода

 Skills.find({ skillbranch: branches[i]._id }, function (err, skills) {

Как мы можем добавить await или async к этому перед возвращением?

Я изучаю узел / экспресс и не смог составить синтаксис для использования с некоторыми ответами / примерами в других публикациях в stackoverflow, где они использовали async, await, Promise.

const Skills = require('../models/skills.model.js');
const SkillBranch = require('../models/skillbranch.model.js');

exports.getSkills = function (req, res) {
   let branchSkills = [];       

   SkillBranch.find(function (err, branches) {         
     if (branches) {
        var obj = {
            "status": "200",
            "message": "skills",
            "data": branches
        }

        for (var i = 0; i < branches.length; i++) {                
            Skills.find({ skillbranch: branches[i]._id }, function (err, skills) {
                console.log(JSON.stringify(skills)); //this is returning after res.send()
                branchSkills.push(skills);                                        
            })

            if (i == branches.length - 1) {                    
                var obj = {
                    "status": "200",
                    "message": "skills",
                    "data": branchSkills
                }

                //this is returning before Skills.find() is complete
                res.send(JSON.stringify(obj));
            }
         }
     } else {
        var obj = {
            "status": "500",
            "message": "Getting skills ",
            "data": []
        }
        res.send(JSON.stringify(obj));
     }
  })
};

Ответы [ 2 ]

2 голосов
/ 23 мая 2019

Вы должны позвонить res.send() внутри Skills.find() обратного вызова, а не вне его. Но так как вы вызываете несколько Skills.find(), вам нужно отслеживать, сколько колбэков было возвращено. Для этого вы можете использовать переменную:

// Keep track of completed find():
var completed = 0;

for (var i = 0; i < branches.length; i++) {                
    Skills.find({ skillbranch: branches[i]._id }, function (err, skills) {
        console.log(JSON.stringify(skills));
        completed++;
        branchSkills.push(skills);

        if (completed == branches.length) {
            var obj = {
                "status": "200",
                "message": "skills",
                "data": branchSkills
            }
            res.send(JSON.stringify(obj)); // INSIDE callback
        }
    }) // <--- note that callback ends here!
 }
2 голосов
/ 23 мая 2019

Как-то так должно работать.

Создайте обещание по вызову монго.Как только он завершится, просто преобразуйте его в массив, добавьте его к своим навыкам ветвления и разрешите обещание в новой обновленной версии.Затем отправьте данные с этой новой обновленной версией, а не с глобальным объектом branchSkills, который вы использовали.

Следует отметить, что я не уверен, для чего вы используете навыки веток, но вы можете просторазрешить с skills без нажатия на этот глобальный массив?Это должно исправить ваши проблемы со временем.

new Promise((resolve, reject) => {
  Skills.find({ skillbranch: branches[i]._id }).toArray((err, skills) => {
      if (err) {
        reject(err);
      } else {
        branchSkills.push(skills);
        resolve(branchSkills);
      }          
    });
  });
}).then(updatedBranchSkills => {
  if (i == branches.length - 1) {                    
    var obj = {
      "status": "200",
      "message": "skills",
      "data": updatedBranchSkills
  }

  res.send(JSON.stringify(obj));
});
...