从 2 mongodb 个集合中搜索后的 Nodejs 单个回调
Nodejs single callback after searching from 2 mongodb collections
我有 2 个合集 Stud
和 Prof
。
我有一个函数,它以 id
作为参数,如果 id 属于这个集合中的任何一个,则 returns 相应的信息。
- 第一个函数调用:传递属于
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
}
您可以使用 waterfall method of 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'
});
要获得问题的答案,请申请@abdulbarik post。
这是关于您的实际代码的其他内容:
- 将您的请求分解为函数
- 当您使用回调时,请使用它们来正确 return 错误。不扔。
- 您不需要将
_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
});
和之前的回答一样,你可以使用async模块来完成这个任务。有很多函数可以控制节点的非阻塞特性。这里推荐大家使用"parallel"的方式。由于查询是相互独立的,它会比 "waterfall" 方法更快。
根据您的问题,代码将如下所示。
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
中了解异步方法
我有 2 个合集 Stud
和 Prof
。
我有一个函数,它以 id
作为参数,如果 id 属于这个集合中的任何一个,则 returns 相应的信息。
- 第一个函数调用:传递属于
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
}
您可以使用 waterfall method of 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'
});
要获得问题的答案,请申请@abdulbarik post。
这是关于您的实际代码的其他内容:
- 将您的请求分解为函数
- 当您使用回调时,请使用它们来正确 return 错误。不扔。
- 您不需要将
_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
});
和之前的回答一样,你可以使用async模块来完成这个任务。有很多函数可以控制节点的非阻塞特性。这里推荐大家使用"parallel"的方式。由于查询是相互独立的,它会比 "waterfall" 方法更快。
根据您的问题,代码将如下所示。
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
中了解异步方法