socket.io重复在浏览器刷新时发出事件

时间:2019-01-15 01:43:04

标签: postgresql socket.io pg

我的socket.io实现遇到问题,不知道如何解决。我在LISTEN中使用pg_notify,因此在数据库中修改某个值时,它将向某个客户端发出“ is_logged_in”。

本身运行良好-我的问题是当我刷新页面时,socket.io断开当前的socket_id,照常创建一个新的socket_id,但是发生这种情况时,它正在创建第二个pgsql客户端实例并复制请求-触发“ logged_in”事件2x。

如果我再次刷新页面,然后手动触发pg“ logged_in”触发器,则它将发出3次,等等。我有泄漏。

const io = require('socket.io')();
const pg = require('pg');

io.on('connection', (socket) => {

  const pgsql = new pg.Client({
      (host, port, user, pass, db)
  })

  pgsql.connect()
  pgsql.query("LISTEN logged_in");

  pgsql.on('notification', function (data) {
        socket.to(json.socket_id).emit('is_logged_in', { status:'Y' });
  });

  socket.on('disconnect', () => {
    //pgsql.end();
  });

});

我试图杀死pgsql实例(在socket.on断开连接中),但是由于某些原因,当我这样做时LISTEN停止工作。

我也尝试将新的pg.Client移到io.on连接之外,但是当我刷新页面时,旧的socket_id断开连接,新的socket_id连接,并且它从不执行代码来重新创建pg客户端。

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

这些可能会造成问题:

  • pgsql实例是在每个套接字连接请求上创建的,并且在断开连接时不会被破坏
  • notification处理程序不会在断开连接时被删除

我对postgres不太熟悉,但是我在socket方面做了大量的工作。因此,类似这样的方法应该可以解决您的问题:

const io = require('socket.io')();
const pg = require('pg');

const pgsql = new pg.Client({
   (host, port, user, pass, db)
})

pgsql.connect();

io.on('connection', (socket) => {
  pgsql.query("LISTEN logged_in");

  const handler = function (data) {
     socket.to(json.socket_id).emit('is_logged_in', { status:'Y' });
     // You could also do pgsql.off('notification', handler) here probably
     // or check if pgsql.once method is available as we need to call this handler only once?
  }

  pgsql.on('notification', handler);

  socket.on('disconnect', () => {
    pgsql.off('notification', handler);
    //pgsql.end(); // Call it in server termination logic
  });

});