好的,我很难过。
我一直在关注一些教程,并设法在nodejs / express中创建一个基本的用户注册/登录应用程序。我还在socket.io聊天中添加了。当用户登录时,他们被定向到聊天页面,他们可以在那里实时聊天。
我目前已将其设置为当用户发布消息时,我们从其会话cookie中获取用户名,然后在将消息插入mongoDB时使用它。当发送新消息时,套接字会将其发送给与聊天相关联的所有人。
我的问题是,当我发送消息时,它最初显示为" undefined:message here"屏幕上。如果我然后刷新整个页面,实际的用户名会显示如下:" Mike:此处的消息"。我已经在提交例程中记录了用户名并且它确实显示了,所以我很困惑为什么它在我发送消息时不会在页面上打印出来。
以下是我发送邮件时的外观截图:
如果我然后刷新页面,这就是它的样子:
这是我的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>
如果有人能指出我失踪的东西,我将非常感激!我知道我需要将我的代码分成模块等,并将其清理干净 - 但是在我这样做之前,我试图修复这部分。我是节点和表达的新手,所以请原谅我对这一切的无知。
非常感谢你的时间
答案 0 :(得分:1)
我很确定你的问题是这样的:
io.emit('output', [data]);
在新输入中,您的数据仅包含消息:
socket.emit('input', {
message: self.value
});
刷新后,您将从数据库中获取正确存储用户名的值。
基本上,你可以在发回数据之前将chatUserName附加到数据中,这可能会解决你的问题。
data.name = chatUserName;
io.emit('output', [data]);