NodeJS:更新或创建MongoDB文档后发送响应

时间:2018-04-10 14:04:04

标签: javascript node.js mongodb mongoose

我有一个nodeJS服务器,它维护一个MongoDB和一个客户端,它在JSON中发送一个带有buildName变量的p​​ost请求。

我要做的是设置一个事件监听器,当具有与客户端发送的buildName匹配的字段的mongoDB文件被更新或创建时触发该事件监听器。多个客户端可以正在侦听,如果更新或创建了包含与其传入的相同buildName的文档,则必须通知它。

我尝试使用这种方法进行轮询,其中我的客户端只是坐在一个while循环中并不断询问是否有更新,但是,我遇到性能问题所以我切换到事件监听器。

我尝试了几种不同的方法来设置回调,当我的客户端发送其post请求时,只要文档更新就会调用该请求,然后将更新的mongodb doc作为res.json发送。我正在使用的一个是mongoose-trigger npm模块,它允许我为创建和更新设置事件监听器。

我还在这里查看可能的解决方案,这些解决方案让我mongoose-trigger获取在创建和更新时触发的事件,但仍然无法找到满足使用此触发来触发对发布请求的响应的答案。

以下是创建触发事件对象的代码片段:

10 const Events = trigger(buildSchema, {
 11   events: {
 12     create: {
 13       select: 'logFile'
 14     },
 15     update: {
 16       select: 'logFile'
 17     }
 18   },
 19   debug: true
 20 });
 21
 22 module.exports = {
 23   Build: mongoose.model('build', buildSchema),
 24   Events: Events
 25 };

上面的代码片段设置了mongoose-trigger npm模块,然后在我的server.js中我在我的帖子路径中使用它,如下所示:

 11 const Model = require('./build');
 12 mongoose.connect('mongodb://vcdep-db/builds');
 13
 14 app.post('/get_build', function(req, res) {
 15   const buildName = req.body.buildName;
 16   console.log(buildName);
 17   Model.Events.on('create', data => {
 18     Model.Build.findById(data._id, function(err, build) {
 19       if (err) console.error(err);
 20
 21       console.log("Created model");
 22       if (build.buildName === buildName)
 23       {
 24         console.log("Document got created", build.buildName);
 26         res.json(build);
 27       }
 28
 29     });
 30   });
 31   Model.Events.on('update', data => {
 32     Model.Build.findById(data._id, function(err, build) {
 33       if (err) console.error(err);
 34
 35       console.log("Updated model");
 36       if (build.buildName === buildName)
 37       {
 38         console.log("Document got updated", build.buildName);
 40         res.json(build);
 41       }
 42
 43     });
 44   });
 45 });

上面的代码第一次更新或创建文档时工作,但是,当我执行相同的过程时,我得到一个Error: Can't set headers after they are sent.我相信这是因为mongoose-trigger设置的监听器不会被删除我发送res.json(build)所以当同一文档再次更新时,它会尝试从先前的客户端回调中执行相同的res.json,这会触发该错误。

我考虑在这里删除事件监听器,看看mongoose-trigger是否允许这样的东西,但尚未找到解决方案。

我相信一旦发送了响应,我就能解除触发器的绑定,它应该修复错误,但我可能错了。如果有人可以提供帮助,我会非常感激!

另外,我并不喜欢使用mongoose-trigger,所以如果有更好的方法来监听mongoDB更新或创建此类事件我非常愿意将其更改为其他内容。

1 个答案:

答案 0 :(得分:1)

一旦调用了其中一个回调对,就需要删除它们。为了能够这样做,你不能使用任何功能,但必须使用命名函数:

app.post('/get_build', function(req, res) {
  const buildName = req.body.buildName;
  console.log(buildName);

  function onCreate(data) {
    Model.Build.findById(data._id, function(err, build) {
      if (err) console.error(err);

      console.log("Created model");
      if (build.buildName === buildName) {
        console.log("Document got created", build.buildName);

        // clean up the event listeners
        Model.Events.removeListener('create', onCreate);
        Model.Events.removeListener('update', onUpdate);

        res.json(build);
      }

    });
  }

  function onUpdate(data) {
    Model.Build.findById(data._id, function(err, build) {
      if (err) console.error(err);

      console.log("Updated model");
      if (build.buildName === buildName) {
        console.log("Document got updated", build.buildName);

        // clean up the event listeners
        Model.Events.removeListener('create', onCreate);
        Model.Events.removeListener('update', onUpdate);

        res.json(build);
      }

    });
  }

  Model.Events.on('create', onCreate);
  Model.Events.on('update', onUpdate);
});

但这仍然是一个糟糕的设计,更好的方法是使用socket.io或类似的东西。