【问题标题】:NodeJS: Send Response after MongoDB Document has been updated or createdNodeJS:在更新或创建 MongoDB 文档后发送响应
【发布时间】:2018-09-20 04:41:59
【问题描述】:

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

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

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

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

我还在这里寻找可能的解决方案,将我带到mongoose-trigger 以获取在创建和更新时触发的事件,但仍然找不到使用此触发触发对发布请求的响应的满意答案。

这里是创建触发事件对象的sn-p代码:

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 };

上面的 sn-p 设置了 mongoose-trigger npm 模块,然后在我的 server.js 中我在我的 post 路由上使用它,如下所示:

 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 更新或创建这种类型的事件,我非常愿意将其更改为其他东西。

【问题讨论】:

  • @kgangadhar 使用 mongoose-trigger 模块,一次只能触发其中一个事件。因此,如果文档被更新,则只会触发第二个文档,并且与创建相同。我也只使用更新触发器对其进行了测试,因此也只有一个 res.json 但无济于事。
  • 如果您使用事件,为什么不使用 Model.Events.on('end' 在完成时发送响应,而不是从“创建”和“更新”发送。
  • 所以我看起来好像您的设计存在一般缺陷。在我看来,一旦发生变化,您似乎想使用诸如 socket.io 之类的东西来通知客户端。即使取消绑定已修复,它看起来仍然很容易出错,并且您可能会错过事件。
  • @NCoop,t.niese 是对的。在这种情况下就是这样
  • @t.niese,你认为解决这个问题的方法是什么?

标签: javascript node.js mongodb mongoose


【解决方案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 或类似的东西。

【讨论】:

  • 像魅力一样工作。谢谢!我会听取您的建议并考虑为此使用 socket.io。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-04
  • 2017-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多