-
Notifications
You must be signed in to change notification settings - Fork 329
第四章 用户上线
现在,我们来给聊天室添加用户上线提醒。
这时我们就要用到 socket.io 了,打开 app.js ,修改 http.createServer(app)
为 server
,并在之前添加如下代码:
var server = http.createServer(app);
var io = require('socket.io').listen(server);
io.sockets.on('connection', function (socket) {
});
修改 views/index.html ,在 <script type="text/javascript" src="javascripts/jquery.cookie.js"></script>
下一行添加:
<script src="/socket.io/socket.io.js"></script>
<script type="text/javascript" src="javascripts/chat.js"></script>
在 public/javascripts 文件夹下新建 chat.js ,内容如下:
$(document).ready(function() {
var socket = io.connect();
});
至此,我们就可以在 Express 中使用 socket.io 了。
接下来我们添加用户上线提醒,流程图如下:
对应代码修改如下:
打开 chat.js ,在 var socket = io.connect();
下添加如下代码:
var from = $.cookie('user');//从 cookie 中读取用户名,存于变量 from
var to = 'all';//设置默认接收对象为"所有人"
//发送用户上线信号
socket.emit('online', {user: from});
socket.on('online', function (data) {
//显示系统消息
if (data.user != from) {
var sys = '<div style="color:#f00">系统(' + now() + '):' + '用户 ' + data.user + ' 上线了!</div>';
} else {
var sys = '<div style="color:#f00">系统(' + now() + '):你进入了聊天室!</div>';
}
$("#contents").append(sys + "<br/>");
//刷新用户在线列表
flushUsers(data.users);
//显示正在对谁说话
showSayTo();
});
接下来我们完成刷新用户在线列表的函数 flushUsers() ,添加如下代码:
//刷新用户在线列表
function flushUsers(users) {
//清空之前用户列表,添加 "所有人" 选项并默认为灰色选中效果
$("#list").empty().append('<li title="双击聊天" alt="all" class="sayingto" onselectstart="return false">所有人</li>');
//遍历生成用户在线列表
for (var i in users) {
$("#list").append('<li alt="' + users[i] + '" title="双击聊天" onselectstart="return false">' + users[i] + '</li>');
}
//双击对某人聊天
$("#list > li").dblclick(function() {
//如果不是双击的自己的名字
if ($(this).attr('alt') != from) {
//设置被双击的用户为说话对象
to = $(this).attr('alt');
//清除之前的选中效果
$("#list > li").removeClass('sayingto');
//给被双击的用户添加选中效果
$(this).addClass('sayingto');
//刷新正在对谁说话
showSayTo();
}
});
}
添加显示正在对谁说话的函数 showSayTo() ,代码如下:
//显示正在对谁说话
function showSayTo() {
$("#from").html(from);
$("#to").html(to == "all" ? "所有人" : to);
}
添加获取当前时间的函数 now() ,代码如下:
//获取当前时间
function now() {
var date = new Date();
var time = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ' ' + date.getHours() + ':' + (date.getMinutes() < 10 ? ('0' + date.getMinutes()) : date.getMinutes()) + ":" + (date.getSeconds() < 10 ? ('0' + date.getSeconds()) : date.getSeconds());
return time;
}
最后,修改 app.js ,在 io.sockets.on('connection')
里添加如下代码:
//有人上线
socket.on('online', function (data) {
//将上线的用户名存储为 socket 对象的属性,以区分每个 socket 对象,方便后面使用
socket.name = data.user;
//users 对象中不存在该用户名则插入该用户名
if (!users[data.user]) {
users[data.user] = data.user;
}
//向所有用户广播该用户上线信息
io.sockets.emit('online', {users: users, user: data.user});
});
注意:我们把存储用户名的操作放到用户上线的事件里(即 socket.on('online')
里),而不是用户登录时把直接用户名存储到数组。这是因为 “用户上线添加用户名,用户下线删除用户名” 这是一个对称的操作。假如用户登录时把用户名存储到数组,用户下线时从数组中删除用户名,那么当用户刷新聊天室页面或者关闭然后重新打开页面时(都会触发一个下线并上线的动作),users 数组中就会只删除而不再重新添加该用户,即右侧的 “在线用户” 列表也不会显示该用户名了。
至此,我们完成了聊天室用户上线提醒。运行你的 app ,打开两个浏览器试试吧!