Javascript 承诺传播中间对象(NodeJS和MongoDB)
我试图在Node 4.x中将MongoDB与承诺一起使用 在本例中,我想:Javascript 承诺传播中间对象(NodeJS和MongoDB),javascript,node.js,mongodb,ecmascript-6,es6-promise,Javascript,Node.js,Mongodb,Ecmascript 6,Es6 Promise,我试图在Node 4.x中将MongoDB与承诺一起使用 在本例中,我想: 连接到我的mongodb 然后用给定的密钥删除所有内容 然后插入一条记录 然后关闭连接 幸运的是,mongodb客户机在您不回叫它的情况下做出了承诺。这是我想到的 const MongoClient=require('mongodb')。MongoClient; const test=require('assert'); 函数insertDoc(doc,collName){ 返回MongoClient.connect('
const MongoClient=require('mongodb')。MongoClient;
const test=require('assert');
函数insertDoc(doc,collName){
返回MongoClient.connect('mongodb://localhost:27017/myDB')
。然后(db=>{
const col=db.collection(collName);
返回col.deleteMany({'Key':doc.Key})
.然后(()=>col.insertOne(doc))
.then(result=>test.equal(1,result.insertedCount))
.然后(()=>db.close);
});
}
代码似乎正常,但嵌套的
.then()
“感觉”错误。有什么办法可以在我准备.close()
对象时使用db
对象吗?现在,您可以使用外部范围中的变量来实现这一点:
let db;
function insertDoc(doc, collName) {
return MongoClient.connect(dsn)
.then(connectedDb => {
db = connectedDb;
return col.deleteMany(doc)
}) // now you can chain `.then` and still use `db`
}
有几种可能的替代方法,比如传递db
,但这对我来说似乎很奇怪。如果希望保持此流,但仍然利用异步性,可以使用async
/wait
。现在,您需要一个transpiler(如babel)和类似于再生器运行时的东西来使用它
async function insertDoc(doc, collName) {
const db = await MongoClient.connect(dsn);
const col = db.collection(collName);
await col.deleteMany({Key: doc.key});
const result = await col.insertOne(doc);
await test.equal(1, result.insertedCount) // is this asynchronous?
return db.close();
}
您也可以使用/
yield
来避免传输,尽管它有点冗长。我发现您必须的是我见过的最具可读性的替代模式。我自己使用缩进(嵌套。然后)来访问以前的值(这是我唯一一次这么做!)
很多事情最终会影响代码的外观和读取。以您的col
temporary为例。如果不需要,您的代码可能如下所示:
var insertDoc = (doc, collName) => MongoClient.connect('mongodb://localhost:x/DB')
.then(db => db.collection(collName).deleteMany({ 'Key': doc.key })
.then(() => db.collection(collName).insertOne(doc))
.then(result => test.equal(1, result.insertedCount))
.then(() => db.close))
.then(() => doSomethingElse());
注意db.close)之后的额外)
。括号匹配的编辑器很有用。:)
我不是为了代码的美观而建议删除col
。我之所以显示它,是因为我认为它突出显示了缩进如何很好地显示db
值的范围。当我看到这样的代码时,我开始喜欢这种模式
在现实生活中,代码并不总是整齐地折叠,但我喜欢这样一种模式,它可以在可能的情况下折叠。一种选择是将承诺更多地视为价值,然后在需要时取出包装好的价值。但它也有其可读性的缺点
e、 g
我有时会做第一个,但它不是很干净的范围。它可能有一些副作用,比如db
在它应该被垃圾收集后仍然存在。在可读性方面,我有时会使用它,但我发现称它为haveDb
是有益的,可以将它与它的值区分开来。e、 g.haveDb.then(db=>{})
。就像“当我有db的时候,就用它来做这个”。很好。我喜欢这个比我刚才做的稍微好一点你的代码和嵌套的then
s没有问题(除了你应该使用finally
notthen
作为close
回调)@Bergi没有。es6中有没有最后的,但是你仍然需要它的功能来关闭
@Bergi。然后(()=>db.close(),e=>(db.close(),Promise.reject(e))
或者类似的东西,同意。
function insertDoc(doc, collName) {
const db = MongoClient.connect('mongodb://localhost:27017/myDB');
const col = db.then(db => db.collection(collName));
return col.deleteMany({ 'Key': doc.key })
.then(() => col.insertOne(doc))
.then(result => test.equal(1, result.insertedCount))
// You've still got the 'db' promise here, so you can get its value
// to close it.
.then(() => db.then(db => db.close()));
}