【发布时间】: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