前端开发与java开发哪个好 |
java开发前端后端 |
web前端开发 java |
这次本来准备做一个基于话题讨论的小程序,需要用到im,所以就做了一个demo,初步实现了im功能。
im需要使用websocket实现功能,微信小程序实现了websocket接口,可以直接使用;服务端这边选用了ws包,比较简单上手。
一、小程序实现
1、连接wss wx.connectSocket()
2、发送消息 wx.connectSocket(JSON.stringify(msg))
3、监听消息 wx.onSocketMessage()
4、只要界面保持,保持连接 ,微信这边如果超过60s无响应,会自动关闭socket
javascript 代码
var timerId = 0,
_this = this
var timeout = 55000
function keepAlive() {
wx.sendSocketMessage({
data: JSON.stringify({
type: ‘keep’,
}),
})
console.log(‘keep alive’)
}
timerId = setInterval(function() {
keepAlive()
}, timeout)
5、关闭连接
javascript 代码
wx.onSocketClose(function(res) {
console.log(‘WebSocket 已关闭!’)
})
二、服务端
1、wss首先需要配置nginx,这里共用了https的证书
2、搭建wss服务器
wss = new WebSocketServer({
port: 4000
});
3、监听客户端
整体思路是:所有的聊天数据全部换存在redis里面,每日定时任务schedule更新数据到数据库中
每次客户端获取聊天数据是从redis里面获取,最多50条数据记录
为了识别用户,每次连接ws后,客户端会发送一条type=log的用户,夹带者用户user_id和话题chat_id,然后服务器端将该用户放置到对应聊天室内
客户端发送聊天数据,type=msg, 服务器会实时广播给所有客户端,并将聊天记录存入对应redis
客户端断开连接用户数据从redis列表中移除
每次重启node服务器会断开所有的ws连接需要作出判断
javascript 代码
/**
* Create websocket server.
*/
var WebSocketServer = require(‘ws’).Server
var chatDao = require(‘../../dao/chatDao’)
var schedule = require(‘node-schedule’) //定时任务
var Redis = require(‘ioredis’)
var redis = new Redis()
var async = require(‘async’) //事件控制
module.exports = {
// 连接池
clients: {},
connectionIDCounter: 0,
//定时任务
createSchedule: function(time) {
var rule = new schedule.RecurrenceRule()
rule.hour = time
// rule.second = time;
var j = schedule.scheduleJob(rule, function() {
console.log(‘scheduleJob’)
//所有话题入库
async.waterfall(
[
function(callback) {
redis.get(‘chat’).then(function(result) {
callback(null, JSON.parse(result))
})
},
],
function(err, results) {
var l = results.length
for (var i = 0; i < l; i++) {
redis.get(‘chat’ + results[i]).then(function(result) {
result = JSON.parse(result)
var l = result.content.length //可能不存在聊天记录
// 聊天记录数据超过200的留下最新的50条记录在redis,其他的数据全部入库
if (l >= 200) {
var arr = result.content.slice(0, l – 50) //截取数组
//把对象的转成纯数组
var values = []
arr.forEach(function(n, i) {
var _arr = []
for (var m in n) {
if (
m != ‘avatarUrl’ &&
m != ‘nickName’
) {
_arr.push(n[m])
}
}
values.push(_arr)
})
result.content = result.content.slice(l – 51, l) //留下50条记录
redis.set(‘chat67’, JSON.stringify(result)) // 保证有初始值,json转数组
//更新聊天记录表
chatDao.updatechatRecordbythemeId(
values,
function(err, ret) {
console.log(ret)
},
)
}
})
}
},
)
})
},
//用户插入到话题列表
addUserIntoWSuser: function(ws, msg) {
var _this = this
redis.get(‘chat’ + msg.theme_id).then(function(result) {
result = JSON.parse(result)
console.log(‘redis theme list: ‘, result)
//存入用户id
try {
if (result.user.indexOf(msg.user_writer_id) < 0) {
result.user.push(msg.user_writer_id)
// console.log(msg);
}
} catch (err) {
result = {
theme_id: msg.theme_id,
content: [],
user: [],
}
result.user.push(msg.user_writer_id) //存入用户id
}
//创建话题的缓存
if (!_this.clients.hasOwnProperty(‘chat’ + msg.theme_id)) {
_this.clients[‘chat’ + msg.theme_id] = []
}
ws.id = _this.connectionIDCounter++
_this.clients[‘chat’ + msg.theme_id].push(ws) //用户入群
console.log(
‘addUserIntoWSuser: ‘,
_this.clients,
result.user,
ws._socket._handle.fd,
)
redis.set(‘chat’ + msg.theme_id, JSON.stringify(result)) //数据成功存储到redis
})
},
//话题存入缓存中
addContentIntoWScontent: function(msg) {
redis.get(‘chat’ + msg.theme_id).then(function(result) {
result = JSON.parse(result)
result.content.push(msg) //存入聊天记录
console.log(‘addContentIntoWScontent: ‘, result.content)
redis.set(‘chat’ + msg.theme_id, JSON.stringify(result)) //数据成功存储到redis
})
},
//初始化websocket服务器
initWebSocketServer: function() {
var _this = this
var msgTmp
// 监听websocket服务器
wss = new WebSocketServer({
port: 4000,
})
this.createSchedule(3) //每天凌晨3点定时任务
wss.on(‘connection’, function(ws) {
// console.log(ws);
ws.on(‘message’, function(message) {
if (message) {
msgTmp = JSON.parse(message)
if (msgTmp.type == ‘msg’) {
//话题存入缓存中
_this.addContentIntoWScontent(msgTmp)
try {
_this.clients[‘chat’ + msgTmp.theme_id].forEach(
function callback(ws1, index, array) {
console.log(‘broadcast: ‘, message)
if (ws.isAlive === false)
_this.clients[
‘chat’ + msgTmp.theme_id
].splice(index, 1)
ws1.send(message)
},
)
} catch (err) {
console.error(err, new Date())
}
} else if (msgTmp.type == ‘log’) {
// 用户数据将该连接加入连接池
_this.addUserIntoWSuser(ws, msgTmp)
} else if (msgTmp.type == ‘keep’) {
console.log(message)
} else {
console.log(message)
}
}
})
// 连接关闭时,将其移出对应话题连接池
ws.on(‘close’, function(message) {
console.log(message)
})
})
},
}
java前端累还是开发累 |
java web前端开发流程 |
学java还是前端开发 |
» 本文来自:前端开发者 » 《前端开发基于node.js的im初实现》
» 本文链接地址:https://www.rokub.com/8148.html
» 您也可以订阅本站:https://www.rokub.com
评论前必须登录!
注册