MongoDB承诺和结果处理

目前我正在学习nodejs中的Promise,现在我在处理mongoDB查询和承诺方面有点困难。 以下是我在下面的示例代码。

db.collection(module.exports.collectionName).find( {"$or" :[{"email":req.body.email},{"username":req.body.username}]},function(err,success){ if (err) {throw new Error("Error in accessing DB - check new user"); } return success; }).toArray().then(function(value){ console.log(value.length); if (value.length == 0) { db.collection(module.exports.collectionName).insertOne(insert,function(err,success){ if (err) {throw new Error("Error in accessing DB - insert new");} return success; }).then(function(value){ return resolve("Success") }).catch(function(value){ return reject("Error happened during accessing DB, please contact the Admin inside"); }); } return reject("Email / Username is not unique"); }).catch(function(value){ return reject("Error happened during accessing DB, please contact the Admin"); }); 

对不起,代码中有很多乱七八糟的东西。 我想问几个关于查询处理的事情。 首先,我们如何正确处理mongodb查询中的错误,据此处理

 ,function(err,success){ if (err) {throw new Error("Error in accessing DB - check new user"); } return success; }). 

一段代码?

在toArray()之后添加“then”解决了我以前的promise的问题,当它到达db插入代码时还没有解决。 但是,现在我有另一个数据库查询里面,我怎么正确(再次)处理asynchronous调用? 上面的例子是否正确?

在DB中没有重复的情况下运行这个代码(意味着第一个查询返回null)将导致返回拒绝代码“在访问数据库时发生错误,请联系pipe理员”(最后一个拒绝)。 但是,数据库更新正常,这意味着它应该达到那么而不是赶上。 查询应该已经打到中间部分的决心,并返回,但似乎代码触发捕获莫名其妙。

这个问题似乎归结为承诺如何工作。 看起来代码中有两个相关但是不同的事情:

  1. 使用Mongo返回的promise。
  2. 控制另一个承诺(也许这个函数返回)。

我们似乎也错过了一个细节 – 这是否在一个函数中返回另一个承诺? 现在让我们假设你是,看起来像这样:

 function addNewUser(req) { return new Promise(function(resolve, reject) { // Insert the code from the question here. }); } 

承诺确实只能“设置”一次。 他们可以resolvedrejected 。 然而,随后的then()catch()调用返回新的Promise。 这可以让你链接在一起来控制应用程序的stream程。 同样,您可以从promise处理函数中返回一个新的Promise,让它们按顺序工作。

所以你的MongoDB查询可能看起来像这样:

 // First, run the initial query and get a Promise for that db.collection(module.exports.collectionName).find(...) .then(function(existingUsers) { // Now that we found what we need, let's insert a new value return db.collection(module.exports.collectionName).insertOne(...) }) .then(function(addedUser) { // Now we know that we found existing users and insert a new one resolve(addedUser); // This resolves the Promise returned from addNewUser() }); 

这可以控制MongoDB操作的顺序。 如果你需要针对不同情况进行特殊的error handling(比如MongoDB错误和用户已存在的错误),你可以在需要的地方添加条件检查和调用catch() 。 例如:

 // First, run the initial query and get a Promise for that db.collection(module.exports.collectionName).find(...) .then(function(existingUsers) { if (existingUsers.length < 1) { // Now that we found what we need, let's insert a new value return db.collection(module.exports.collectionName).insertOne(...) } // Throw an error indicating we're in a bad place throw new Error('A user with this name already exists!'); }) .then(function(addedUser) { // Now we know that we found existing users and insert a new one resolve(addedUser); // This resolves the Promise returned from addNewUser() }) .catch(function(err) { // This will run when an error occurs. It could be a MongoDB error, or perhaps the user-related error thrown earlier. reject(err); // This rejects the Promise returned from addNewUser() }); 

感谢道格swain之前!

现在看来我对mongodb和诺言了解得更多。 前面的代码的问题是,我试图过度复杂的callback和承诺。 代码function(err,success)实际上是一个callback,应该处理结果。 添加承诺。 那么没有必要。

然而,正如我试图promisify所有的节点,我改变了代码使用诺言,而不是callback。 这是最后的代码,更整洁。

 db.collection(module.exports.collectionName).find(...).toArray().then(function(value2){ if (value2.length > 0){ return reject("Email / Username is not unique"); } db.collection(module.exports.collectionName).insertOne(insert).then(function(correct){ return resolve(correct); }).catch(function(error){ throw new Error(error); }); }).catch(function(err){ console.log(err); return reject(err); }); 

代码的工作就像我想要的。 之前的代码也有问题,因为在find(...)之后不能直接使用。 find(...)查询将返回一个游标而不是一个promise。 因此.toArray()需要使用。然后。