使用Monk的Mongo数据库:如果数据库关闭,则会出现错误捕获和处理

时间:2017-08-09 00:53:26

标签: javascript node.js mongodb error-handling monk

我是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})
    }

});

1 个答案:

答案 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回调参数来捕获错误。当这些结构中的任何一个实际上都在使用时,同样的原则适用。