【问题标题】:Nodejs single callback after searching from 2 mongodb collections从 2 个 mongodb 集合中搜索后的 Nodejs 单个回调
【发布时间】:2018-02-24 07:30:10
【问题描述】:

我有 2 个集合 StudProf

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

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

预期结果:首先获得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
}

【问题讨论】:

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


    【解决方案1】:

    你可以使用asyncmudule的waterfall方法来解决这个问题

    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】:

      如需回答您的问题,请申请@abdulbarik 帖子。

      这是关于您的实际代码的其他内容:


      • 将您的请求分解为函数
      • 当您使用回调时,请使用它们正确返回错误。不要扔。
      • 您不需要将_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
        });
      

      【讨论】:

      • 感谢对代码进行更正。我很欣赏您解释的方式,但是如@Shawon 所示应用了异步并行
      【解决方案3】:

      和之前的回答一样,你可以使用 async 模块来完成这个任务。有许多功能可以控制节点的非阻塞性质。在这里我会推荐你​​使用“并行”的方法。由于查询是相互独立的,它会比“瀑布”方法更快。

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

      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
          }
      }
      

      );

      您可以从asyn documentation 了解异步方法

      【讨论】:

        猜你喜欢
        • 2016-09-04
        • 2021-04-17
        • 2014-07-31
        • 2013-12-02
        • 1970-01-01
        • 2018-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多