JavaScript For循环始终返回最后一次出现或最后一个元素

时间:2018-04-18 05:20:10

标签: javascript socket.io

说明:

我目前正在使用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;};

Console.log & Appending to HTML DIFFERENCE

1 个答案:

答案 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。这应该修改。