2017-09-15 61 views
1

我有2个集合StudProf从2个mongodb集合中搜索后Nodejs单个回调

我有一个函数,需要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

正如前面的回答,您可以使用异步模块来完成这一任务。有很多功能可以控制节点的非阻塞性质。在这里我会推荐你​​使用“并行”方法。由于查询彼此独立,它将比“瀑布”方法更快。

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

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

1

您可以使用方法的async mudule到了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' 
}); 
1

为了回答你的问题,适用@abdulbarik岗位。

下面是其他的东西,你的实际代码:


  • 削减你的请求转换功能
  • 当您使用回调,使用它们来正确地返回错误。不要丢。
  • 你并不需要把_id钥匙插进报价

备注:

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

样品约回调和功能切。我让你做其余的是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 
    }); 
+1

**感谢异步方法**对代码进行更改。我赞赏你解释的方式,然而应用@Shawon所示的异步并行 –