正确处理Node Promise中的异步Mongo操作 [英] Correct handling of async Mongo actions in Node Promise
问题描述
我有一个执行多个Mongo动作的函数,最后一个动作是在完成所有其他动作后关闭数据库.我对这个问题的处理非常有信心,但是我有一些外部评论引起了人们的关注,我想验证我的解决方案是否正确.
I have a function which performs multiple Mongo actions, and the last action is to close the database after all other actions have completed. I was fairly confident of my handling of the issue, but I have had some external comments raise concerns, and I wanted to verify if my solution is correct.
建议的解决方案:
function updateDatabase (name, token) {
return new Promise((resolve, reject) => {
MongoClient.connect(MONGODB_URL)
.then( (database) => {
return database.collection('testCollection').update({name}, {$pull: {tokens: {$in: [token]}}})
.then( () => {
database.collection('log').insert({
name,
token
});
return database;
})
})
.then( (db) => {
db.close(true);
resolve(`Invalid token: ${token} has been removed from: ${name}`);
})
.catch( (err) => {
reject(err);
})
});
}
我的原始解决方案:
function updateDatabase (name, token) {
return new Promise((resolve, reject) => {
MongoClient.connect(MONGODB_URL)
.then( (database) => {
return database;
})
.then( (db) => {
database.collection('testCollection').update({name}, {$pull: {tokens: {$in: [token]}}})
return database;
})
.then( () => {
database.collection('log').insert({
name,
token
});
return database;
})
.then( (db) => {
db.close(true);
resolve(`Invalid token: ${token} has been removed from: ${name}`);
})
.catch( (err) => {
reject(err);
})
});
}
我的原始解决方案是否可行?建议的解决方案是更好的方法吗?两者都可以在测试中工作,但是要针对生产级负载,因此我需要确保在其他操作完成之前,数据库不会关闭,我相信这是我在原始解决方案中已经完成的.
Is my original solution way off the mark or is the suggested solution a better approach? Both work in testing but against a production grade load, I need to make sure the db does not close until other actions are complete, which I believe I have accomplished in my original solution.
推荐答案
由于MongoDB驱动程序的所有异步操作已经返回了promise,因此您根本不应该使用new Promise
,而是建立一个promise链:>
Since all asynchronous operations of the MongoDB driver already return a promise, you shouldn't use new Promise
at all, but set up a promise chain:
function updateDatabase(name, token) {
let database;
return MongoClient.connect(MONGODB_URL).then(db => {
database = db;
return database
.collection("testCollection")
.update({ name }, { $pull: { tokens: { $in: [token] } } });
})
.then(() => {
return database.collection("log").insert({
name,
token
});
})
.then(() => {
database.close(true);
})
.catch(err => {
database.close(true);
throw err;
});
}
我知道您想将database
作为下一个then
的参数传递,但是您会遇到一个问题,即它在catch
处理程序中将不可用.一种解决方案是使用函数作用域变量,该变量将在打开连接后分配,就像上面的代码一样.
I understand that you want to pass database
as an argument for the next then
, but you'll run into the issue that it won't be available in the catch
handler. One solution is to use a function-scoped variable that gets assigned after opening the connection, like the code above does.
如果您不喜欢,可以在.then
处理程序内为MongoClient.connect
创建一个新的Promise链:
If you don't like that, you can create a new promise chain inside the .then
handler for MongoClient.connect
:
function updateDatabase(name, token) {
return MongoClient.connect(MONGODB_URL).then(database => {
return database
.collection("testCollection")
.update({ name }, { $pull: { tokens: { $in: [token] } } })
.then(() => {
return database.collection("log").insert({
name,
token
});
})
.then(() => {
database.close(true);
})
.catch(err => {
database.close(true);
throw err;
});
});
}
这篇关于正确处理Node Promise中的异步Mongo操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!