Nodejs从2个mongodb集合中搜索后进行单次回调

时间:2017-09-15 07:20:53

标签: node.js mongodb express mongoose async.js

我有2个集StudProf

我有一个以id为参数的函数,如果id属于任何一个集合,则返回相应的信息。

  • 第一个函数调用:传递属于id集合
  • Prof
  • 第二个函数调用:传递属于id集合
  • Stud

预期结果:首先获得Prof结果,然后获得Stud结果。

但是由于nodejs的异步特性,我总是首先获得Stud结果,然后获得Prof结果。

无论如何通过引入新变量或更改查询集合的方式来完成此任务?

非常感谢任何帮助

var check_user_info = function(userid, callback) {
    Stud.findOne({
        '_id': userid
    }, function(err, stud) {
        if (err)
            throw err
        if (stud) {
            callback(stud);
        } else {
            Prof.findOne({
                '_id': userid
            }, function(err, prof) {
                if (err)
                    throw err
                if (prof) {
                    callback(prof);
                } else {
                    callback(false);
                }
            })
        }
    })
    return
}

3 个答案:

答案 0 :(得分:3)

如前所述,您可以使用异步模块来完成此任务。有许多功能可以控制节点的非阻塞性质。在这里,我将建议您使用“并行”方法。由于查询彼此独立,因此它将比“瀑布式”方法更快。

根据您的问题,代码将如下所示。

var async = require('async');

async.parallel([
    cb=>{

        Stud.findOne({
        '_id': userid
        },cb);
    },
    cb=>{

        Prof.findOne({
        '_id': userid
        },cb);

    }
],(err,result)=>{
        if(err) {
            //handle error
            return;
        }

            //result will be an array where the first element will be the result of first query and
            // second element will be the query result for the second query
            // so according to this .....

        if(result[0]){
            //id is matched with Stud collection
            //result[0] is the student doc
        }else if(result[1]) {
            //id is matched with Prof collection
            //result[0] is the professor doc
        }else {
            //Neither Stud or Prof
        }
});

您可以从this other post

中了解异步方法

答案 1 :(得分:1)

您可以使用waterfall mudule的async方法解决此问题

async.waterfall([
    function(callback) {
        //your fist query method can go here
        callback(null, query_result1);
    },
    function(first_result1, callback) {
        // your second query method go here
        callback(null, query_result2);
    }
], function (err, result) {
    // final result'
});

答案 2 :(得分:1)

要回答您的问题,请申请@abdulbarik post。

以下是有关您实际代码的其他内容:

  • 将您的请求剪切为函数
  • 使用回调时,请使用它们正确返回错误。不要扔。
  • 您无需将_id键放入引号

说明:

  • 由于您使用的是现在支持ES6(大部分)的node.js,请使用它。阅读更简单,效率更高。

关于回调和功能切换的示例。我让你做其余的es6,瀑布处理......你可以看看Promise和Async / Await模式。

// Check if there is a student
function check_student(user_id, callback) {
  Stud.findOne({
    _id: user_id
  }, function (err, stud) {
    if (err) return callback(err, false);

    // stud here can worth false
    return callback(false, stud);
  });
}
// Check if there is a prof
function check_prof(user_id, callback) {
  Prof.findOne({
    _id: user_id
  }, function (err, prof) {
    if (err) return callback(err, false);

    // prof here can worth false
    return callback(false, prof);
  });
}
// Get Stud not Prof info
function check_user_info(user_id, callback) {
  // Look if user_id match a stud
  check_student(user_id, function (err, result) {
    // We have an error
    if (err) return callback(err, false);

    // We have a student
    if (result) return callback(false, result);

    // Check if user_id match a prof
    check_prof(user_id, function (err, result) {
      // We have an error
      if (err) return callback(err, false);

      // We have a prof
      if (result) return callback(false, result);

      // No result at all
      return callback(false, false);
    });
  });
}

你怎么称呼它

check_user_info(user_id, function (err, result) {
  // ...
});

承诺代码示例:

        // Check if there is a student
        function check_student(user_id) {
          return new Promise((resolve, reject) => {
            Stud.findOne({
              _id: user_id
            }, (err, stud) => {
              if (err) return reject(err);

              // prof here can worth false
              return resolve(stud);
            });
          });
        }

        // Check if there is a prof
        function check_prof(user_id) {
          return new Promise((resolve, reject) => {
            Prof.findOne({
              _id: user_id
            }, (err, prof) => {
              if (err) return reject(err);

              // prof here can worth false
              return resolve(prof);
            });
          });
        }

        // Get Stud not Prof info
        function check_user_info(user_id) {
          return Promise.all([
            check_student(user_id),
            check_prof(user_id),
          ]);
        }
check_user_info(user_id)
  .then([
    stud,
    prof,
  ] => {
    // Handle result
  })
  .catch((err) => {
    // Handle error
  });