我正在使用实时应用,我正在使用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('/');
}
}
}
答案 0 :(得分:1)
页面刷新会终止套接字连接并创建一个新连接。这将发生在网络中断或任何其他会破坏连接的情况。
答案 1 :(得分:0)
您没有显示足够的代码来跟踪整个流程,但在我看来,您可能在controllers.js文件中有do-it
消息的重复事件处理程序。
每次使用经过身份验证的请求调用controllers.js中的.index()
方法时,您将在此行代码中为do-it
消息添加另一个事件处理程序:
socket.on('do-it', function(data){...});
这将导致您每次到达时多次处理该消息,从而导致重复的数据库插入。
因此,您实际上并没有获得重复的消息,您只是按预期为一段给定的数据获取消息,但是您安装了重复的事件处理程序,每个事件处理程序都处理消息。
通常,像这样的问题的答案是将事件处理程序移出多次发生的代码,因此事件处理程序只在代码初始化期间添加一次。看起来您可以严格执行此操作,因为您还尝试在同一代码中使用req
。我必须为controllers.js看到更大的代码上下文,以了解您实际上要做的事情以及解决问题的好方法。
仅供参考,您在此处所做的是使用http事件处理程序的混合套接字事件处理程序(将一个事件处理程序放在另一个事件处理程序中)。这几乎不会起作用,因为这两个事件发生在不同的时间,你最终会遇到重复的处理程序。