刷新页面时Socket.io多个连接

时间:2017-09-06 19:38:23

标签: javascript node.js sockets express socket.io

我正在使用实时应用,我正在使用Socket.io来获取此功能。

到目前为止,当用户发布内容(文本)时,我的套接字服务器收到此消息,然后发送到我的控制器以将此数据保存在数据库(MySQL)上。然后通过相同的套接字服务器将相同的消息返回给客户端。

实际上这很有效,但是当我刷新浏览器并发布新消息时,数据会在数据库中插入两次,因此我在客户端收到相同的两条消息。每次刷新页面时都会发生这种情况,所以如果我刷新页面10次,我会在数据库中插入10条带有相同数据的消息。

这是我现在的代码,任何帮助都会很棒。

SocketServer.js

var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);

//websockets
var messages = 'Recibido';
var Usuarios = 0;
var storeUsers = [];

app.use(express.static('public'));

io.sockets.on('connection', function(socket) {
  Usuarios++;

  console.log('Usuarios totales: ' + Usuarios);
  io.sockets.emit('users-connected', Usuarios);

  var clients = io.sockets.clients();
  var conectados = clients.connected;

  console.log('------------------ROOM-------------------------');
  for (client in conectados) {
    var color = '\x1b[32m' + client;
    console.log('id: ' + color, '\x1b[0m');
  }
  console.log('\x1b[0m', '-----------------------------------------------');

  socket.on('disconnect', function() {
    Usuarios--;
    var desconectao = '\x1b[31m' + socket.id
    console.log('Socket desconectado: ' + desconectao, '\x1b[0m');
    io.sockets.emit('users-connected', Usuarios);
    socket.removeAllListeners();
  });

  socket.on('new-publication', function(data){
    console.log('Mensaje del usuario: ' + data.pub);
    io.sockets.emit('do-it', data)
  })

  socket.on('do-publication', function(data){

    console.log('Info: ' + data.nombre);
    io.sockets.emit('do-publication', data)
  })

});

http.listen(8081, function() {
  console.log("websockets corriendo en el puerto 8081");
});

Controller.js

var mysql = require('mysql');
var io = require('socket.io-client');
var socket = io.connect('http://localhost:8081', {transports: ['websocket'], upgrade: false});


module.exports = {

    index: function(req,res,next){

        if (req.isAuthenticated()) {

            var config =require('.././database/config');
            var db = mysql.createConnection(config);

            db.query('SELECT publicaciones.publicacion, publicaciones.fecha_pub, publicaciones.imagen ,users.nombre AS nombre, users.image AS image FROM publicaciones JOIN users ON publicaciones.id_user = users.id ORDER BY fecha_pub DESC', function(err, rows, fields){

                resultado    = rows;

                var message = {
                    isAuthenticated : req.isAuthenticated(),
                    items: resultado,
                    user: req.user,
                };

                res.render('users/panel',message);

            });

            socket.on('users-connected', function(data){
                console.log('Conectado al servidor Websockets');
                console.log('Usuarios conectados: ' + data);
            });

            socket.on('do-it', function(data){
                var datos_pub;
                console.log(data.pub);
                var currentdate = new Date();
                var datetime = currentdate.getFullYear() + "-"
                + (currentdate.getMonth()+1) + "-"
                + currentdate.getDate() + " "
                + currentdate.getHours() + ":"
                + currentdate.getMinutes() + ":"
                + currentdate.getSeconds();

                var publicacion = {
                    id_user : req.user.id,
                    publicacion : data.pub,
                    imagen : null,
                    fecha_pub : datetime
                };

                function loadSelect(id) {

                    var resultado = {};
                    db.query('SELECT publicaciones.publicacion, publicaciones.fecha_pub, users.nombre AS nombre, users.image AS image FROM publicaciones JOIN users ON publicaciones.id_user = users.id where id_publicacion=' + id, function(err, rows, fields){


                        socket.emit('do-publication', {
                            nombre: rows[0].nombre,
                            publicacion: rows[0].publicacion,
                            fecha: rows[0].fecha_pub,
                            image: rows[0].image
                        });
                    });
                }

                db.query('INSERT INTO publicaciones SET ?', publicacion, function(err, rows, fields){
                    if(err) throw err;
                    //db.end();
                    datos_pub =  rows.insertId;
                    loadSelect(datos_pub);

                });
          });

        }else{

                res.render('users/signin',{
                    isAuthenticated : req.isAuthenticated(),
                    user : req.user,
                    publicacion : req.publicacion,
                    messages : req.flash('info')
                });
        }
    }
}

Jquery脚本(客户端)

$(document).ready(function(){

  var socket = io.connect('http://localhost:8081', {transports: ['websocket'], upgrade: false});

  socket.on('do-publication', function(data){
    console.log(data.image);
    var imageprofile = "http://localhost:3000/images/upload_images/"+data.image;
    var $items = $('<div id="card-container" class="grid-item"><div class="card"><img class="avatar" src="'+imageprofile+'"><div class="name">'+data.nombre+'</div><div class="date">'+data.fecha+ '</div><p class="card">'+data.publicacion+'</p></div></div>');
    $grid.prepend( $items )
    .masonry( 'prepended', $items );
  })

  socket.on('users-connected', function(data){
    console.log('Usuarios conectados: ' + data);
  })

  $('#Button-Post-Publication').click(function(e){
    e.preventDefault();
    var publication = $('#Text-Area-Publication').val();    
    socket.emit('new-publication', {pub: publication})


  })
})

已更新为Passport和中间件

Passport.js

var LocalStrategy = require('passport-local').Strategy;
var mysql= require('mysql');
var bcrypt = require('bcryptjs');

module.exports = function(passport){

    passport.serializeUser(function(user, done){
        done(null, user);
    });

    passport.deserializeUser(function(obj,done){
        done(null,obj);
    });

    passport.use(new LocalStrategy({
        passReqToCallback: true

    }, function(req,email,password,done){

        var config = require('.././database/config');

        var db = mysql.createConnection(config);
        db.connect();

        db.query('SELECT * FROM users WHERE email = ?',email, function(err,rows,fields){
            if(err) throw err;
            db.end();
            if(rows.length > 0){

                var user = rows[0];
                if (bcrypt.compareSync(password,user.password)) {
                    return done (null,{
                        id: user.id,
                        nombre: user.nombre,
                        email: user.email,
                        image : user.image
                    });
                }
            }

            return done(null,false, req.flash('authmessage','Email o Password incorrecto'));
        });


    }
    ));

};

中间件

module.exports ={
    isLogged:function(req,res,next){
        // si esta autentificado continua en caso contrario ira a la página de registro
        if(req.isAuthenticated()){
            next();
        }else{
            res.redirect('/');
        }
    }
}

2 个答案:

答案 0 :(得分:1)

页面刷新会终止套接字连接并创建一个新连接。这将发生在网络中断或任何其他会破坏连接的情况。

答案 1 :(得分:0)

您没有显示足够的代码来跟踪整个流程,但在我看来,您可能在controllers.js文件中有do-it消息的重复事件处理程序。

每次使用经过身份验证的请求调用controllers.js中的.index()方法时,您将在此行代码中为do-it消息添加另一个事件处理程序:

 socket.on('do-it', function(data){...});

这将导致您每次到达时多次处理该消息,从而导致重复的数据库插入。

因此,您实际上并没有获得重复的消息,您只是按预期为一段给定的数据获取消息,但是您安装了重复的事件处理程序,每个事件处理程序都处理消息。

通常,像这样的问题的答案是将事件处理程序移出多次发生的代码,因此事件处理程序只在代码初始化期间添加一次。看起来您可以严格执行此操作,因为您还尝试在同一代码中使用req。我必须为controllers.js看到更大的代码上下文,以了解您实际上要做的事情以及解决问题的好方法。

仅供参考,您在此处所做的是使用http事件处理程序的混合套接字事件处理程序(将一个事件处理程序放在另一个事件处理程序中)。这几乎不会起作用,因为这两个事件发生在不同的时间,你最终会遇到重复的处理程序。