微信小程序聊天室demo-微信小程序demo兼职
HTTP的生命周期大致是这样的,一个请求,一个响应,这个请求结束; HTTP 1.1改进了,增加了一个keep-alive,作用是在这个HTTP连接中,可以发送多个请求,接受多个响应,但本质上,request = response,也就是说,总有一个-请求和响应之间的一一对应。 当没有请求时,服务器不能主动响应。
WebSocket
客户端和服务端完成协议升级后(HTTP -> WebSocket),建立持久连接。 它有多耐用? 此连接可以持续到客户端或服务器主动关闭连接为止。 与HTTP最大的区别在于,此时服务端可以主动向客户端推送消息。在本项目中,我们使用socket.io包模块来实现WebSocket。 Socket.io不仅实现了对WebSocket的封装,还将其与Ajax轮询等实时通信方式一起封装成一个通用的接口。 这样做的原因是的,当服务器不支持WebSocket的时候,可以转换成其他的实现方式,啧啧,堪称丝滑享受
下一步是实施部分。 前端引入socket.io.js文件后应该做什么?
谈话很便宜,告诉你代码。
var socket = io.connect();
是的,就这么简单,不信你去看官方文档。
输入昵称完成登录
这里的“登录”并不是真正的登录。 io.connect()执行后,连接建立,这里要处理一些交互行为。
监听前端的连接事件。 该事件的触发条件为:成功与服务器建立连接。
socket.on('connect',function(){
//do something
});
回调里面是此时要完成的DOM操作,比如:
更改提示文本(最初是“连接到服务器...”)
显示覆盖
焦点文本框
当用户输入昵称并点击登录按钮时,当前套接字向服务器触发登录事件:
socket.emit('login',nickname);
携带一个参数,为用户输入的昵称。
当服务器检查此昵称的有效性并通过时触发:
socket.on('loginSuccess', function(){
//1. 隐藏登录层
//2. 用户可以愉快和别人聊天了~
});
如果用户输入的昵称无效,触发:
socket.on('loginFailed', function(){
//1. 提示用户昵称哪里出问题了
//2. 等待用户重新输入
});
注意这里的事件名称,比如login、loginSuccess、loginFailed都是自定义的,只要和服务器一致就可以了。
发送信息
想象一下用户发送消息的操作,并将其分解:输入文本 -> 单击发送。 就是这两个,ok,这里需要在发送按钮上挂一个事件,告诉服务器,“服务器服务器,这里是socket XXX,我给你发消息了,注意查收,结束。”
socket.emit('msgSend',msg);
接受一个参数,即用户的输入。
接受讯息
接受消息的逻辑分为三种情况
自己发的消息
别人发来的消息
系统提示信息
别着急,让我们一一来看。
自己发的消息
你发送的消息直接显示在聊天消息面板,你不需要和后台交互接收你发送的消息,你只需要告诉后台这是我给你发的消息。 当然你也可以仿微信对你发送的消息进行处理:发送的时候在聊天面板添加你的消息->旁边放个小菊花或者加载->后台交互->隐藏消息成功的菊花; 如果失败,小菊花会变成红色感叹号,表示用户发送失败。
别人发来的消息
现在需要在前端创建一个监听事件来响应服务器端的“新消息”。
socket.on('newMsg', function(nickname, msg){
//显示这条新消息
});
回调函数中有两个参数nickname和msg,分别是消息发送者的昵称和消息内容。 这两个怎么来的? 别着急,后面会在服务端的逻辑中讲到。 这里只需要知道前端收到新消息时,因为涉及到显示新消息,所以需要这两个参数。
系统提示信息
系统的提示信息主要有两种:
提示新加入和退出的用户
显示当前在线用户数
大概是这样的,所以需要在前端监听系统事件
socket.on('system', function(nickname, count, type){
//1.根据系统事件类型(新加入或离开)来提示用户
//2.修改在线用户数量
});
这里的三个参数也是必不可少的。 nickname代表触发系统事件的用户昵称,count代表当前在线用户数,type代表事件类型(加入/离开)。 同样,这三个参数也是从服务器传来的。
背景逻辑
对应前端,后台逻辑主要分为以下几个部分
启动服务
建立连接
用户登录
接受用户发送的消息并进行广播
处理系统消息
启动服务
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
app.use('/',express.static(__dirname + "/www"));
server.listen(8080);
因为我把前端文件(html/js/css)放在了www文件夹下,所以我用express指定返回给浏览器的页面路径。
当然,除了express,还必须引入socket.io模块并绑定到服务端。
建立连接
服务准备好了,如何建立连接呢?
io.on('connection', function(socket){
//do something
});
就是这样…?
昂首挺胸。
你没有看错微信小程序聊天室demo,我也没有看错,下面是对应的前端逻辑:
var socket = io.connect();
socket.on('connect', function(){
//do something
});
建立连接后,就可以编写所有关于socket活动的逻辑了。 (仅供参考:当然,它是写在这个连接事件的回调中)
用户登录
还记得前端触发的登录事件叫什么吗?
socket.emit('login', nickname);
叫做登录,它还带了一个参数——用户要给自己起的昵称nickname。好了,我们来写对应的后台逻辑
socket.on('login', function(nickname){
//do something
});
do something here 是做什么的? 也就是检查用户输入的昵称是否合法,比如是否已经存在,长度限制,符号限制等。球都是麻袋,好像哪里不对……
长度限制和符号限制? 这两个哥们根本不用在服务端做,直接在前端做就可以了。 所以我们只剩下一个问题了——昵称的唯一性。
既然要检查昵称是否唯一,首先要有当前在线用户的昵称集合。 不然去哪里查看昵称是否存在呢?
所以需要全局维护一个数组来保存当前在线用户的昵称
var users = [];
在这个数组中找到用户通过登录事件传递的昵称。 如果不存在,说明当前昵称是合法的,用户可以调用这个名字。 然后
socket.nickname = nickname;//记录下当前socket的nicknameusers.push(nickname);
socket.emit('loginSuccess');//触发loginSuccess事件
如果昵称已经存在,则触发登录失败事件,前端进行相应交互。
socket.emit('loginFailed');
接收来自用户的消息和
根据约定的事件名称编写服务端监听器
socket.on('msgSend', function(msg){
socket.broadcast.emit('newMsg', socket.nickname, msg);
});
这里调用的api是socket的广播事件微信小程序聊天室demo,作用是将消息广播给除当前socket之外的所有socket。
处理系统消息
剩下的工作就是处理系统消息了,首先我们要知道有哪些系统消息
当用户输入的昵称通过合法性校验后,系统提示新添加的用户
io.sockets.emit('system',nickname, users.length, 'login');
io.sockets.emit()
作用是向当前所有的socket触发一个事件,区别于socket.broadcast.emit()。
按照上面的代码,编写用户离开时的广播事件:
io.sockets.emit('system', nickname, users.length, 'logout');
但是写在哪里呢?这时候需要在服务端监听一个额外的断开连接事件。
socket.on('disconnect', function(){
var index = users.indexOf(socket.nickname);
users.splice(index, 1);//将断开用户的昵称从全局数组users中删除
io.sockets.emit('system', socket.nickname, users.length, 'logout');
});
总结
至此,就算完成了一个基于Node.js的聊天室,当然还有很多可以优化的地方,但是核心功能就这些,能看到这里的都是好人,因为我写的它并阅读它,我感觉真的很好。 像老太太的裹脚布——又臭又长