在异步/等待Express路由器中管理MongoDB客户端的正确方法是什么?
我正在尝试在路由器中间件中创建MongoDB客户端,以便它可用于所有请求。这是一个简化的示例:
const express = require('express');
const { MongoClient } = require('mongodb');
let router = express.Router();
router.use(async (req, res, next) => {
try {
req.client = await MongoClient.connect(process.env.MONGODB_URI);
next();
} catch (err) {
next(err);
} finally {
req.client && req.client.close();
}
});
router.get('/', async (req, res, next) => {
let user = await users.findOne({ name: 'foo' });
if (!user) {
user = { name: 'foo' };
await users.insert(user);
}
res.json(user);
});
module.exports = router;
不幸的是,在调用await users.findOne({ name: 'foo' })
之后,执行跳转到中间件中的finally
分支,MongoDB连接已关闭,因此对await users.insert(user)
的潜在调用因此失败。 / p>
感谢帮助!
答案 0 :(得分:0)
您从哪里获得用户集合?
在正确地收集了用户的集合之后,您可以保证所有的数据库调用。
您可以使用Promise.all一次解决所有问题
const [user1, user2] = await Promise.all([users.findOne({name: 'user1'}), users.findOne({name: 'user2'})]);
这将同时解决两个承诺。
代码更新后编辑1
您可以使用{upsert: true}
const user = await users.findOneAndUpdate({name: 'foo'}, {name: 'foo'}, {upsert: true})
并且由于next()是异步调用,因此您的代码肯定会移动到finally块。
const express = require('express');
const { MongoClient } = require('mongodb');
let router = express.Router();
router.use(async (req, res, next) => {
try {
req.client = await MongoClient.connect(process.env.MONGODB_URI);
next();
} catch (err) {
next(err);
}
});
router.get('/', async (req, res, next) => {
let user = await users.findOne({ name: 'foo' });
if (!user) {
user = { name: 'foo' };
await users.insert(user);
}
res.json(user);
next();
});
router.use(async (req, res, next) => {
try {
req.client && req.client.close();
} catch (err) {
next(err);
}
})
module.exports = router;