我是Mongo的新手。我需要一个简单项目的数据库,并最终使用Mongo和Monk的教程,但我在理解如何处理错误方面遇到了问题。
背景:我在客户端有一个注册表单。当用户单击按钮时,数据通过AJAX发送到控制器(在验证时,但现在不相关)将此类数据插入数据库并发回成功或错误。所有数据库都启动时似乎工作正常。
问题:如果我没有启动数据库并尝试发送请求,则不会返回错误。没有任何反应。在控制台上一段时间后,我得到: POST / members / addmember - - ms - - 。
我认为在这种情况下应该向用户返回一些错误,那么我怎么能这样做呢?
帖子请求如下(几乎与教程相同):
// app.js
var db = monk('localhost:27017/dbname')
[...]
// I realize it might be not optimal here
app.use(function(req,res,next){
req.db = db;
next();
});
// members.js
router.post('/addmember', function(req, res) {
var db = req.db;
var collection = db.get('memberstest');
collection.insert(req.body, function(err, result){
res.json(
(err === null) ? { msg: 'success' } : { msg: err }
);
});
});
如果数据库已关闭,我猜问题实际上甚至比插入更早,即“ db.get()”。那么如何检查 get 是否可以实际完成?我认为,鉴于节点的异步性质,像try / catch这样的东西在这里毫无意义。正确的吗?
编辑:在Neil的回答和一些尝试之后,我把以下似乎完成这项工作放在一起。但是,鉴于我对此的信心十分可信,如果下面的代码有效,我会很感激,因为它有意义或偶然。我添加了bufferMaxEntries:0选项并修改了控制器,如下所示。在ajax回调中,我现在只有一个警告,显示抛出的错误消息(如果有的话)。router.post('/addmember', async (req,res) => {
try {
let db = req.db;
let collection = db.get('memberstest');
collection.insert(req.body, function(err, result){
res.json(
(err === null) ? { msg: 'success' } : { msg: err }
);
});
await db.then(() => 1);
} catch(e) {
res.json({msg: e.message})
}
});
答案 0 :(得分:1)
您实际上可以设置bufferMaxEntries
选项(在Db
下记录但在该对象使用中已弃用,在"顶层使用,而不是#34;)在连接上,基本上停止"排队"当没有连接实际存在时请求驱动程序。
作为一个最小的例子:
<强> index.js 强>
const express = require('express'),
morgan = require('morgan'),
db = require('monk')('localhost/test',{ bufferMaxEntries: 0 }),
app = express();
const routes = require('./routes');
app.use(morgan('combined'));
app.use((req,res,next) => {
req.db = db;
next();
});
app.use('/', routes);
(async function() {
try {
await db.then(() => 1);
let collection = db.get('test');
await collection.remove({});
await collection.insert(Array(5).fill(1).map((e,i) => ({ a: i+1 })));
console.log('inserted test data');
await app.listen(3000,'0.0.0.0');
console.log('App waiting');
} catch(e) {
console.error(e);
}
})();
<强> routes.js 强>
var router = require('express').Router();
router.get('/', async (req,res) => {
try {
let db = req.db,
collection = db.get('test');
let response = await collection.find();
res.json(response);
} catch(e) {
res.status(500).json(e);
}
});
module.exports = router;
所以我实际上正在等待数据库连接至少出现在&#34;启动&#34;这里,但实际上只是因为我想插入一些数据来实际检索。它不是必需的,但基本概念是等待Promise
解决:
await db.then(() => 1);
有点琐碎,而且实际代码并不是真正需要的。但我仍然认为这是一种很好的做法。
真正的测试是通过停止mongod
或以其他方式使服务器无法访问然后发出请求来完成的。
由于我们将连接选项设置为{ bufferMaxEntries: 0 }
,这意味着当您尝试向数据库发出命令时立即,如果没有实际连接,则会返回失败。
当然,当数据库再次可用时,您将无法获得错误,并且指示将正常发生。
如果没有该选项,则默认为&#34; en-queue&#34;解决连接之前的操作,然后是&#34;缓冲区&#34;本质上是&#34;播放&#34;。
你可以通过&#34;停止&#34;模拟这个(就像我一样) mongod
守护进程和发出请求。然后&#34;开始&#34;守护进程和发出请求。它应该只返回捕获的错误响应。
注意:不是必需的,但实际上
async/await
语法的全部目的是让try..catch
之类的内容再次生效,因为您实际上可以将范围视为块而不是使用Promise.catch()
或err
回调参数来捕获错误。当这些结构中的任何一个实际上都在使用时,同样的原则适用。