说明:
我目前正在使用node.js和socket.io开发一个聊天应用程序...我的问题是什么...当用户X向用户Y发送消息时,反之亦然我存储在mongo DB中...所以我想显示从Y到用户X收到的消息计数以及从X到Y收到的消息计数,如下图所示。
问题: 如果我做console.log它正在工作,但如果我将消息的数量附加到html,那么它只显示最后一次出现
Here is the screen shot which contains two online users with last occurrence messages count..
以下是客户端Java脚本代码。
阅读以下代码中的评论以理解
$(function() {
var socket = io('/chat');
var username = $('#user').val();
var noChat = 0; //setting 0 if all chats histroy is not loaded. 1 if all chats loaded.
var msgCount = 0; //counting total number of messages displayed.
var oldInitDone = 0; //it is 0 when old-chats-init is not executed and 1 if executed.
var roomId; //variable for setting room.
var toUser;
//passing data on connection.
socket.on('connect', function() {
socket.emit('set-user-data', username);
// setTimeout(function() { alert(username+" logged In"); }, 500);
socket.on('broadcast', function(data) {
document.getElementById("hell0").innerHTML += '<li>' + data.description + '</li>';
// $('#hell0').append($('<li>').append($(data.description).append($('<li>');
$('#hell0').scrollTop($('#hell0')[0].scrollHeight);
});
}); //end of connect event.
var to;
var tocount;
var fromcount;
socket.on('countynew', function(data) {
console.log(data.rec);
console.log(data.count);
console.log(data.fro);
to = data.rec;
});
//receiving online users stack from server node js.
socket.on('onlineStack', function(stack) {
$('#list').empty();
$('#list').append($('<li>').append($('<button id="ubtn" class="btn btn-danger btn-block btn-lg"></button>').text("Group").css({
"font-size": "18px"
})));
var txt_count;
var totalOnline = 0;
//FOR LOOP TO GET ALL THE ONLINE USERS
for (let user in stack) {
//listing all users.
if (user != username && stack[user] == "Online") {
// totalOnline variable count counts how many users are in online
totalOnline++
var fuser = user;
var fusern = username;
var tryit;
// From here i am sending onlineusers list and owner (owner is the perosn who is using this script) to server using socket.io
socket.emit('sendinguserandowner', {
onlineuser: fuser,
owner: fusern
});
//datahit contains whom sent, how many messages sent and who send
socket.on('hitback', function(datahit) {
tryit = datahit;
//datahit.to contains your user name (The person who is currently using this script: owner) // CONSIDER X USING and he
//datahit.to conatins count of messages recieved from datahit.from
//datahit.from contains online users for X // Y, Z, A, B....
console.log(datahit.to + " You recieved " + datahit.count + " from " + datahit.from);
//HERE IS THE PROBLEM
//HERE IS THE PROBLEM
//HERE IS THE PROBLEM
//HERE IS THE PROBLEM
if (datahit.from==fuser) {
$('.county')
.text(datahit.count) // EVERY TIME IT RETURNS LAST OCCORANCE VALUE example : if for loop iterating 3 times like 0,1,2 i am able to see 0,1,2 if i do console.log but if i append to HTML i am getting 2 only
.css({
"float": "center",
"color": "#000",
"font-size": "25px"
});
}
//UP TO HERE IS THE PROBLEM
//UP TO HERE IS THE PROBLEM
//UP TO HERE IS THE PROBLEM
//UP TO HERE IS THE PROBLEM
});
var txt_count = $('<span class="county"></span>')
.text("-")
.css({
"float": "center",
"color": "#000",
"font-size": "25px"
});
var txt1 = $('<button id="ubtn" class="btn btn-success btn-md">').text(user).css({ // HERE I AM APPENDING ONLINE USER'S NAME TO BUTTON
"font-size": "18px"
});
//console.log(user+" "+username); // to view in browser console
var txt2 = $('<span class="badge"></span>').text("*" + stack[user]).css({ // HERE IS THE STATUS OF ONLINE USER WHETHER HE/SHE is ONLINE OR OFFLINE
"float": "right",
"color": "#009933",
"font-size": "18px"
});
$('#list').append($('<li>').append(txt1, txt2, txt_count));// ITERATE BY ABOVE FOR LOOP AND APPAEND ONLINE USER NAMES AND THEIR STATUS TO BUTTONS
}
$('#totalOnline').text(totalOnline);
} //END OF THE FOR.
$('#scrl1').scrollTop($('#scrl1').prop("scrollHeight"));
}); //end of receiving onlineStack event.
//on button click function.
$(document).on("click", "#ubtn", function() {
//empty messages.
$('#messages').empty();
$('#typing').text("");
msgCount = 0;
noChat = 0;
oldInitDone = 0;
//assigning friends name to whom messages will send,(in case of group its value is Group).
toUser = $(this).text();
socket.emit('readed', {
readed: toUser
});
//showing and hiding relevant information.
$('#frndName').text(toUser);
$('#initMsg').hide();
$('#chatForm').show(); //showing chat form.
$('#sendBtn').hide(); //hiding send button to prevent sending of empty messages.
//assigning two names for room. which helps in one-to-one and also group chat.
if (toUser == "Group") {
var currentRoom = "Group-Group";
var reverseRoom = "Group-Group";
} else {
var currentRoom = username + "-" + toUser;
var reverseRoom = toUser + "-" + username;
}
//event to set room and join.
socket.emit('set-room', {
name1: currentRoom,
name2: reverseRoom
});
}); //end of on button click event.
//event for setting roomId.
socket.on('set-room', function(room) {
//empty messages.
$('#messages').empty();
$('#typing').text("");
msgCount = 0;
noChat = 0;
oldInitDone = 0;
//assigning room id to roomId variable. which helps in one-to-one and group chat.
roomId = room;
console.log("roomId : " + roomId);
//event to get chat history on button click or as room is set.
socket.emit('old-chats-init', {
room: roomId,
username: username,
msgCount: msgCount
});
}); //end of set-room event.
//on scroll load more old-chats.
$('#scrl2').scroll(function() {
if ($('#scrl2').scrollTop() == 0 && noChat == 0 && oldInitDone == 1) {
$('#loading').show();
socket.emit('old-chats', {
room: roomId,
username: username,
msgCount: msgCount
});
}
}); // end of scroll event.
//listening old-chats event.
socket.on('old-chats', function(data) {
if (data.room == roomId) {
oldInitDone = 1; //setting value to implies that old-chats first event is done.
if (data.result.length != 0) {
$('#noChat').hide(); //hiding no more chats message.
for (var i = 0; i < data.result.length; i++) {
//styling of chat message.
var chatDate = moment(data.result[i].createdOn).format("MMMM Do YYYY, hh:mm:ss a");
var txt1 = $('<span></span>').text(data.result[i].msgFrom + " : ").css({
"color": "#006080"
});
var txt2 = $('<span></span>').text(chatDate).css({
"float": "right",
"color": "#a6a6a6",
"font-size": "16px"
});
var txt3 = $('<p></p>').append(txt1, txt2);
var txt4 = $('<p></p>').text(data.result[i].msg).css({
"color": "#000000"
});
//showing chat in chat box.
$('#messages').prepend($('<li>').append(txt3, txt4));
msgCount++;
} //end of for.
// $('#county').text(msgCount);
console.log(msgCount);
} else {
$('#noChat').show(); //displaying no more chats message.
noChat = 1; //to prevent unnecessary scroll event.
}
//hiding loading bar.
$('#loading').hide();
//setting scrollbar position while first 5 chats loads.
if (msgCount <= 5) {
$('#scrl2').scrollTop($('#scrl2').prop("scrollHeight"));
}
} //end of outer if.
}); // end of listening old-chats event.
// keyup handler.
$('#myMsg').keyup(function() {
if ($('#myMsg').val()) {
$('#sendBtn').show(); //showing send button.
socket.emit('typing');
} else {
$('#sendBtn').hide(); //hiding send button to prevent sending empty messages.
}
}); //end of keyup handler.
//receiving typing message.
socket.on('typing', function(msg) {
var setTime;
//clearing previous setTimeout function.
clearTimeout(setTime);
//showing typing message.
$('#typing').text(msg);
//showing typing message only for few seconds.
setTime = setTimeout(function() {
$('#typing').text("");
}, 3500);
}); //end of typing event.
//sending message.
$('form').submit(function() {
socket.emit('chat-msg', {
msg: $('#myMsg').val(),
msgTo: toUser,
date: Date.now()
});
console.log("2. TO:" + toUser + " Message is:" + $('#myMsg').val() + " Line 202 in ScriptForChat file")
$('#myMsg').val("");
$('#sendBtn').hide();
return false;
}); //end of sending message.
//receiving messages.
unread = 0;
socket.on('chat-msg', function(data) {
unread++;
//styling of chat message.
var chatDate = moment(data.date).format("MMMM Do YYYY, hh:mm:ss a");
var txt1 = $('<span></span>').text(data.msgFrom + " : ").css({
"color": "#006080"
});
var txt2 = $('<span></span>').text(chatDate).css({
"float": "right",
"color": "#a6a6a6",
"font-size": "16px"
});
var txt3 = $('<p></p>').append(txt1, txt2);
var txt4 = $('<p></p>').text(data.msg).css({
"color": "#000000"
});
console.log("2. From:" + data.msgFrom + " Message is:" + data.msg)
//showing chat in chat box.
$('#messages').append($('<li>').append(txt3, txt4));
msgCount++;
console.log(msgCount);
$('#typing').text("");
$('#scrl2').scrollTop($('#scrl2').prop("scrollHeight"));
}); //end of receiving messages.
//on disconnect event.
//passing data on connection.
socket.on('disconnect', function() {
//showing and hiding relevant information.
$('#list').empty();
$('#messages').empty();
$('#typing').text("");
$('#frndName').text("Disconnected..");
$('#loading').hide();
$('#noChat').hide();
$('#initMsg').show().text("...Please, Refresh Your Page...");
$('#chatForm').hide();
msgCount = 0;
noChat = 0;
}); //end of connect event
}); //end of function
以下是 SERVER SIDE NODE JS 文件 SOCKET.IO
var socketio = require('socket.io');
var mongoose = require('mongoose');
var events = require('events');
var _ = require('lodash');
var eventEmitter = new events.EventEmitter();
//adding db models
require('../app/models/user.js');
require('../app/models/chat.js');
require('../app/models/room.js');
//using mongoose Schema models
var userModel = mongoose.model('User');
var chatModel = mongoose.model('Chat');
var roomModel = mongoose.model('Room');
//reatime magic begins here
module.exports.sockets = function (http) {
io = socketio.listen(http);
//setting chat route
var ioChat = io.of('/chat');
var userStack = {};
var oldChats, sendUserStack, setRoom;
var userSocket = {};
//socket.io magic starts here
ioChat.on('connection', function (socket) {
console.log("socketio chat connected.");
//function to get user name
socket.on('set-user-data', function (username) {
console.log(username + " logged In");
//HERE IS THE MAIN CODE WHICH WILL EXECUTE WHEN sendinguserandowner emits from CLIENT.JS
socket.on('sendinguserandowner', function (data) {
// Here using mongo i am retriving count of messages
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
MongoClient.connect(url, function (err, db) {
if (err) throw err;
var dbo = db.db("rio_chat");
dbo.collection("chats").find({
msgFrom: data.onlineuser,
msgTo: data.owner,
unread: "1"
}).count(function (err, result) {
if (err) throw err;
//DATAHIT IN CLIENT SIDE IS SAME AS HERE but this is for server side console
console.log(data.owner + " You recieved " + result + " from " + data.onlineuser);
// HERE I AM HITTING BACK TO BROWSER
socket.emit('hitback', {
to: data.owner,
count: result,
from: data.onlineuser
});
db.close();
});
});
});
//storing variable.
socket.username = username;
userSocket[socket.username] = socket.id;
socket.broadcast.emit('broadcast', {
description: username + ' Logged In'
});
//getting all users list
eventEmitter.emit('get-all-users');
//sending all users list. and setting if online or offline.
sendUserStack = function () {
for (i in userSocket) {
for (j in userStack) {
if (j == i) {
userStack[j] = "Online";
}
}
}
//for popping connection message.
ioChat.emit('onlineStack', userStack);
} //end of sendUserStack function.
}); //end of set-user-data event.
//setting room.
socket.on('set-room', function (room) {
//leaving room.
socket.leave(socket.room);
//getting room data.
eventEmitter.emit('get-room-data', room);
//setting room and join.
setRoom = function (roomId) {
socket.room = roomId;
console.log("roomId : " + socket.room);
socket.join(socket.room);
ioChat.to(userSocket[socket.username]).emit('set-room', socket.room);
};
}); //end of set-room event.
//emits event to read old-chats-init from database.
socket.on('old-chats-init', function (data) {
eventEmitter.emit('read-chat', data);
});
//emits event to read old chats from database.
socket.on('old-chats', function (data) {
eventEmitter.emit('read-chat', data);
});
//sending old chats to client.
oldChats = function (result, username, room) {
ioChat.to(userSocket[username]).emit('old-chats', {
result: result,
room: room
});
}
//showing msg on typing.
socket.on('typing', function () {
socket.to(socket.room).broadcast.emit('typing', socket.username + " : is typing...");
});
socket.on('readed', function (data) {
console.log("TO : " + data.readed + " From : " + socket.username + "");
});
//for showing chats.
socket.on('chat-msg', function (data) {
//emits event to save chat to database.
eventEmitter.emit('save-chat', {
msgFrom: socket.username,
msgTo: data.msgTo,
msg: data.msg,
room: socket.room,
unread: 1,
date: data.date
});
//emits event to send chat msg to all clients.
ioChat.to(socket.room).emit('chat-msg', {
msgFrom: socket.username,
msg: data.msg,
date: data.date
});
});
//for popping disconnection message.
socket.on('disconnect', function () {
console.log(socket.username + " logged out");
socket.broadcast.emit('broadcast', {
description: socket.username + ' Logged out'
});
console.log("chat disconnected.");
_.unset(userSocket, socket.username);
userStack[socket.username] = "Offline";
ioChat.emit('onlineStack', userStack);
}); //end of disconnect event.
}); //end of io.on(connection).
//end of socket.io code for chat feature.
//database operations are kept outside of socket.io code.
//saving chats to database.
eventEmitter.on('save-chat', function (data) {
// var today = Date.now();
var newChat = new chatModel({
msgFrom: data.msgFrom,
msgTo: data.msgTo,
msg: data.msg,
room: data.room,
unread: 1,
createdOn: data.date
});
newChat.save(function (err, result) {
if (err) {
console.log("Error : " + err);
} else if (result == undefined || result == null || result == "") {
console.log("Chat Is Not Saved.");
} else {
console.log("Chat Saved.");
//console.log(result);
}
});
}); //end of saving chat.
//reading chat from database.
eventEmitter.on('read-chat', function (data) {
chatModel.find({})
.where('room').equals(data.room)
.sort('-createdOn')
.skip(data.msgCount)
.lean()
.limit(5)
.exec(function (err, result) {
if (err) {
console.log("Error : " + err);
} else {
//calling function which emits event to client to show chats.
oldChats(result, data.username, data.room);
}
});
}); //end of reading chat from database.
//listening for get-all-users event. creating list of all users.
eventEmitter.on('get-all-users', function () {
userModel.find({})
.select('username')
.exec(function (err, result) {
if (err) {
console.log("Error : " + err);
} else {
//console.log(result);
for (var i = 0; i < result.length; i++) {
userStack[result[i].username] = "Offline";
}
//console.log("stack "+Object.keys(userStack));
sendUserStack();
}
});
}); //end of get-all-users event.
//listening get-room-data event.
eventEmitter.on('get-room-data', function (room) {
roomModel.find({
$or: [{
name1: room.name1
}, {
name1: room.name2
}, {
name2: room.name1
}, {
name2: room.name2
}]
}, function (err, result) {
if (err) {
console.log("Error : " + err);
} else {
if (result == "" || result == undefined || result == null) {
var today = Date.now();
newRoom = new roomModel({
name1: room.name1,
name2: room.name2,
lastActive: today,
createdOn: today
});
newRoom.save(function (err, newResult) {
if (err) {
console.log("Error : " + err);
} else if (newResult == "" || newResult == undefined || newResult == null) {
console.log("Some Error Occured During Room Creation.");
} else {
setRoom(newResult._id); //calling setRoom function.
}
}); //end of saving room.
} else {
var jresult = JSON.parse(JSON.stringify(result));
setRoom(jresult[0]._id); //calling setRoom function.
}
} //end of else.
}); //end of find room.
}); //end of get-room-data listener.
//end of database operations for chat feature.
//to verify for unique username and email at signup.
//socket namespace for signup.
var ioSignup = io.of('/signup');
var checkUname, checkEmail; //declaring variables for function.
ioSignup.on('connection', function (socket) {
console.log("signup connected.");
//verifying unique username.
socket.on('checkUname', function (uname) {
eventEmitter.emit('findUsername', uname); //event to perform database operation.
}); //end of checkUname event.
//function to emit event for checkUname.
checkUname = function (data) {
ioSignup.to(socket.id).emit('checkUname', data); //data can have only 1 or 0 value.
}; //end of checkUsername function.
//verifying unique email.
socket.on('checkEmail', function (email) {
eventEmitter.emit('findEmail', email); //event to perform database operation.
}); //end of checkEmail event.
//function to emit event for checkEmail.
checkEmail = function (data) {
ioSignup.to(socket.id).emit('checkEmail', data); //data can have only 1 or 0 value.
}; //end of checkEmail function.
//on disconnection.
socket.on('disconnect', function () {
console.log("signup disconnected.");
});
}); //end of ioSignup connection event.
//database operations are kept outside of socket.io code.
//event to find and check username.
eventEmitter.on('findUsername', function (uname) {
userModel.find({
'username': uname
}, function (err, result) {
if (err) {
console.log("Error : " + err);
} else {
//console.log(result);
if (result == "") {
checkUname(1); //send 1 if username not found.
} else {
checkUname(0); //send 0 if username found.
}
}
});
}); //end of findUsername event.
//event to find and check username.
eventEmitter.on('findEmail', function (email) {
userModel.find({
'email': email
}, function (err, result) {
if (err) {
console.log("Error : " + err);
} else {
//console.log(result);
if (result == "") {
checkEmail(1); //send 1 if email not found.
} else {
checkEmail(0); //send 0 if email found.
}
}
});
}); //end of findUsername event.
return io;};
答案 0 :(得分:0)
问题在于在接收.county
事件时使用前端javascript代码中的hitback
类更新dom元素
$('.county')
.text(datahit.count) // EVERY TIME IT RETURNS LAST OCCORANCE VALUE example : if for loop iterating 3 times like 0,1,2 i am able to see 0,1,2 if i do console.log but if i append to HTML i am getting 2 only
.css({
"float": "center",
"color": "#000",
"font-size": "25px"
});
这里发生了什么?
当datahit.count is 251
javascript将251
更新为具有类.county
的元素时。
当datahit.count is 33
javascript将33
更新为具有类.county
的元素时。在此操作期间,所有具有类.county
的元素都在DOM中更新。此时,251 gets changed to 33
。
这就是css的工作原理。
您必须更改渲染逻辑才能解决此问题。
<强>更新强>
要解决此问题,当您从服务器发出hitback
事件时,您可以使用JsonArray发送当前和以前的通知(每次发出时都必须执行此操作hitback
事件)并在客户端每次收到hitback
时重新呈现与此通知相关的html元素。
您当前的逻辑更新了hitback
事件发出的单个输入的dom。这应该修改。