我尝试在Node 4.x中使用MongoDB和Promise
在这个例子中,我想:
const MongoClient = require('mongodb').MongoClient;
const test = require('assert');
function insertDoc(doc, collName) {
return MongoClient.connect('mongodb://localhost:27017/myDB')
.then(db => {
const col = db.collection(collName);
return col.deleteMany({ 'Key': doc.key })
.then(() => col.insertOne(doc))
.then(result => test.equal(1, result.insertedCount))
.then(() => db.close);
});
}
代码似乎有效,但嵌套的.then()
"感觉"错误。任何想法如何做到这一点,以便{I}准备db
时可以使用.close()
对象?
答案 0 :(得分:2)
一种选择是将promises更多地视为值,然后在需要时提取包装值。它有自己的可读性缺点。
e.g。
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()));
}
答案 1 :(得分:1)
目前,您可以在外部范围内使用变量来实现此目的:
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
/ await
。现在你需要一个像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();
}
您也可以使用co
/ yield
来避免转换,尽管它有点冗长。
答案 2 :(得分:0)
我发现你所看到的最具可读性的替代方案。我自己使用缩进(嵌套.then
)来访问以前的值(这是我唯一的时间!)
这么多事情最终会影响代码的外观和读取方式。以你的col
临时为例。如果不需要,您的代码可能如下所示:
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
值的范围。就在我看到这样的代码时,我开始喜欢这种模式。
在现实生活中,代码并不总是整齐地崩溃,但我喜欢它可以做到的模式。