socket.io输出是未定义的,直到我刷新页面,然后它出现?

时间:2016-01-14 21:20:23

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

好的,我很难过。

我一直在关注一些教程,并设法在nodejs / express中创建一个基本的用户注册/登录应用程序。我还在socket.io聊天中添加了。当用户登录时,他们被定向到聊天页面,他们可以在那里实时聊天。

我目前已将其设置为当用户发布消息时,我们从其会话cookie中获取用户名,然后在将消息插入mongoDB时使用它。当发送新消息时,套接字会将其发送给与聊天相关联的所有人。

我的问题是,当我发送消息时,它最初显示为" undefined:message here"屏幕上。如果我然后刷新整个页面,实际的用户名会显示如下:" Mike:此处的消息"。我已经在提交例程中记录了用户名并且它确实显示了,所以我很困惑为什么它在我发送消息时不会在页面上打印出来。

以下是我发送邮件时的外观截图:

enter image description here

如果我然后刷新页面,这就是它的样子:

enter image description here

这是我的app.js:

var mongo = require('mongodb').MongoClient;
var bodyParser = require('body-parser');
var bcrypt = require('bcryptjs');
var csrf = require('csurf');
var path = require ('path');
var express = require('express');
var mongoose = require('mongoose');
var uniqueValidator = require('mongoose-unique-validator');
var ios = require('socket.io-express-session');




var moment = require('moment');
var now = moment().format('L');
var http = require('http');
var connect = require('connect');
var secret = 'mysecret';
var cookie = require('cookie');
var cookieParser = require('cookie-parser');
var session = require('express-session')({

    secret: 'mysecret',
    resave:false,
   saveUninitialized: false,
    stringify:true,
    httpOnly: false

});
 var sharedsession = require("express-socket.io-session");
//var MongoStore = require('connect-mongo')(session);


var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;

UserSchema = new Schema({
    //id: ObjectId,

    firstName: String,
    lastName: String,    
    username: {
        type: String,
        unique: true,
        uniqueCaseInsensitive:true
    },
    password: String,
    email: {
        type:String,
         unique: true,
        uniqueCaseInsensitive:true
    },
    accountType: String,
    accountStatus: String,
    acctActivation:{ 
        type:String,
    unique:true
},
joinDate: String

});
UserSchema.plugin(uniqueValidator,{ message: 'Error,  {PATH} {VALUE} has already been registered.\r' });
var User = mongoose.model('User', UserSchema);

var app = express();
app.engine('ejs', require('ejs').renderFile);

app.locals.pretty = true;

//connect to mongo
mongoose.connect('mongodb://localhost/userDB');

//create server

var server = http.createServer(app).listen(3000);
var io = require('socket.io')(server);
console.log('listening on port 3000');


//middleware

app.use(express.static('public'));
app.use(bodyParser.urlencoded({extended:true}));


app.use(session);
  io.use(sharedsession(session, {
  autoSave: true
}));


app.use(csrf());

app.use(function(req,res,next){ // check to see if user already has a session, if so, query mongodb and update the user object
    if(req.session && req.session.user){
        User.findOne({email: req.session.user.email}, function(err, user){
            if(user){
                req.user = user;
                delete req.user.password; // remove password field from session

                req.session.user = req.user;
                res.locals.user = req.user;
            }
            next();
        });
    }else{
        next(); 
    }
});

function requireLogin(req,res,next){ //  check to see if user is logged in, if not, boot em
    if(!req.user){
        res.redirect('/login');
    }else{
        next();
    }
};
function requireAdmin(req,res,next){ // check to see if accountType = Developer (or admin later) - if not, send them to dashboard
    if(req.user.accountType !== 'Developer'){
        res.redirect('/dashboard');
    }else{
        next();
    }
}; 
app.get('/', function(req, res){
    if(req.user){
          res.render('dashboard.ejs');
    }else{
          res.render('index.ejs');
    }

});

app.get('/register', function(req,res){    
    res.render('register.ejs', {csrfToken: req.csrfToken(),
    error:false});
});

app.post('/register', function(req,res){        
    var hash = bcrypt.hashSync(req.body.password, bcrypt.genSaltSync(10));

    var user = new User({
        firstName: req.body.firstName,
        lastName: req.body.lastName,
        username: req.body.username,
        password: hash,
        email: req.body.email,
        accountType: 'Standard',
        accountStatus: 'Active',        
        joinDate: now
    });

    user.save(function(err){
        if(err){
            console.log(err);

            res.render('register.ejs', {csrfToken: req.csrfToken(),
                error: err});

    }else{
       req.session.user = user; //set-cookie
        res.redirect('/dashboard');
    }

    }); 

});

app.get('/login', function(req,res){

    res.render('login.ejs', {
        csrfToken: req.csrfToken(),error:false});
});


app.post('/login', function(req, res){
    User.findOne({username: {$regex: new RegExp('^' + req.body.username, 'i')}}, function(err, user){
        if(!user){

            res.render('login.ejs', {error: 'Invalid username or password combination.',
             csrfToken: req.csrfToken()});
        }else{
            if(bcrypt.compareSync(req.body.password, user.password)){

                req.session.user = user; //set-cookie

                res.redirect('/chat');
            }else{

                res.render('login.ejs', {error: 'Invalid username or password combination.',
                 csrfToken: req.csrfToken()});
            }
        }
    });
});

app.get('/dashboard', requireLogin, function(req,res){   
       res.render('dashboard.ejs');
});
app.get('/chat', requireLogin, function(req,res){   
       res.render('chat.ejs');
});
app.get('/admin', requireLogin, requireAdmin, function(req,res){   //required logged in AND admin status
  // var userlist = User.find({});

   User.find({},{},function(err,docs){

       res.render('admin.ejs',{ "userlist": docs

       }); 

   }) ;



      // res.render('admin.ejs');
});

app.get('/logout', function(req,res){
    req.session.destroy();
    res.redirect('/');
});

mongo.connect('mongodb://127.0.0.1/chat', function(err,db){
    if(err) throw err; 




io.on('connection', function(socket){

var userData = socket.handshake.session;

 var chatUserName = userData.user.username;

  socket.emit('status', 'chatting as '+ chatUserName);
    var col = db.collection('messages');
    sendStatus = function(s){
      socket.emit('status', s);  
    }; 

    //emit all messages (shows old room data)
    col.find().sort({_id: -1}).limit(100).toArray(function(err, res){ 
        if(err) throw err;

        socket.emit('output',res);


    }); 

    //wait for input
    socket.on('input', function(data){

      name = chatUserName,
      message = data.message,
      whitespacePattern = /^\s*$/;

      if(whitespacePattern.test(message)){
          sendStatus('You cannot send an empty message');
      }else{
          col.insert({name: chatUserName, message: message}, function(){
              //emit latest message to all clients 

              io.emit('output', [data]);

         sendStatus({
             message: "Message sent",
             clear: true
         });

          });  
      }

    });

});

});

这是我的chat.ejs文件,它呈现了聊天页面:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Test </title>

        <link rel="stylesheet" href="/css/main.css">


        </head>
     <body>
<h1>Chat</h1>

<div class="chat">

    <div class="chat-messages"><div class="chat-message"></div></div>
    <textarea class="chat-textarea" placeholder="type your message"></textarea>
    <div class="chat-status">Status: <span>Idle</span></div>

</div>
<script src="http://example.com:3000/socket.io/socket.io.js"></script>
<script>
    (function(){
        var getNode = function(s){
            return document.querySelector(s);
        },
        // get required nodes
        status = getNode('.chat-status span'),
        messages = getNode('.chat-messages');
        textarea = getNode('.chat-textarea'),

        statusDefault = status.textContent,


        setStatus = function(s){
            status.textContent = s;

            if(s !== statusDefault){
                var delay = setTimeout(function(){
                  setStatus(statusDefault);
                  clearInterval(delay);
                },3000);
            }
    };

        try{
            var socket = io.connect('http://example.com:3000');
        }catch(e){
            //set status to warn user

        }

        if(socket !== undefined){
            //listen for output

            socket.on('output', function(data){
                data.reverse();
                if(data.length){
                    //loop through results
                    for(var x = 0;x< data.length;x++){

                      var message = document.createElement('div');
                      message.setAttribute('class', 'chat-message');
                       message.textContent = data[x].name + ': ' + data[x].message;

                        //append
                       messages.insertBefore(message, messages.firstChild);
                       messages.appendChild(message);
                       messages.scrollTop = messages.scrollHeight;
          }

                }
            });

            //listen for status
           socket.on('status', function(data){
               setStatus((typeof data === 'object') ? data.message : data);

            if(data.clear === true){
                textarea.value = '';
            }
           });
            //listen for keydown

            textarea.addEventListener('keydown', function(event){
                var self = this;


                if(event.which === 13 && event.shiftKey === false){ //13 is enter, shifKey is shift
                   //send the data
                   socket.emit('input', {

                       message: self.value
                   });

                   event.preventDefault();
                }
            });
        }
    })();
    </script>

如果有人能指出我失踪的东西,我将非常感激!我知道我需要将我的代码分成模块等,并将其清理干净 - 但是在我这样做之前,我试图修复这部分。我是节点和表达的新手,所以请原谅我对这一切的无知。

非常感谢你的时间

1 个答案:

答案 0 :(得分:1)

我很确定你的问题是这样的:

io.emit('output', [data]);

在新输入中,您的数据仅包含消息:

socket.emit('input', { 
    message: self.value
});

刷新后,您将从数据库中获取正确存储用户名的值。

基本上,你可以在发回数据之前将chatUserName附加到数据中,这可能会解决你的问题。

data.name = chatUserName;
io.emit('output', [data]);