我對IM這塊可謂是真正的小白,是以沒接觸過的可以來參考參考。
在微信這個聊天工具裡的小程式上實作聊天功能,總感覺怪怪的。但上司要求了,總是要幹的。
然後就實時通訊這個關鍵詞展開搜尋,穿梭于網頁之間。不過粘貼複制的真的太多了,找了半天也沒找到想要的,不過還是提取到了關鍵詞的WebSocket和node.js的,然後搜尋這兩是啥,什麼關系,總算明白了一點。
最後确定了第一步需要幹的是用node.js搭建服務(我是裝在自己的windows下的):
1.首先到官網下載下傳node.js,下載下傳連結
安裝很簡單,輕按兩下下載下傳好的檔案,直接下一步一步,沒什麼特殊的選擇,路徑預設就好
可以打開指令行視窗輸入 node -v會輸出版本,來檢驗是否安裝成功,其實這個也沒什麼必要
2.然後建立一個檔案夾(我的node.js是安裝在Ç盤的,然後再d盤下建立了個叫webSocket的檔案夾)
然後用指令轉到該目錄下:在這個檔案下安裝我們要使用的子產品:安裝子產品前需要先生成一個配置檔案,不然會報錯(反正我報了)
生成配置檔案指令:npm init -f
執行後可以看到在該檔案下多了一個叫package.json的配置檔案,先不用管(後面也沒管過),接下來繼續安裝子產品的操作
剛開始我是安裝的socket.io,後來發現小程式根本用不了,是以這裡也不說socket.io了。我們這裡用ws
安裝ws指令:npm install --save ws(解除安裝子產品指令:npm uninstall 子產品名字)
3.安裝好子產品後,在你目錄下建立一個.js檔案,我這是一個ws.js
我這裡肯定會比你們的檔案要多,不用在意。
然後打開這個.js檔案,開始編輯你的服務端代碼,這個随便你用記事本還是其他什麼軟體
這是最簡單基礎的一個打開連接配接,響應的代碼:
//引入ws子產品
const WebSocket = require('ws');
//建立服務 port是端口
const wss = new WebSocket.Server({ port: 80});
//用戶端連接配接時會進這個
wss.on('connection', function connection(ws) {
console.log('連接配接成功');
//用戶端發送消息時會觸發這個
ws.on('message', function incoming(data) {
console.log('收到消息');
//data是用戶端發送的消息,這裡clients.foreach是廣播給所有用戶端
wss.clients.forEach(function each(client) {
//把用戶端發來的data,循環發給每個用戶端
client.send(data);
});
});
});
這裡貼上稍微比較完善的代碼,這裡是用資料庫儲存的發送的消息,用的mysql,是以需要在安裝mysql子產品
npm install --save mysql
代碼:
這裡有很多注釋的代碼,都是我鼓搗時用到的,可以無視或删掉
這個MySQL的資料連接配接需要根據自己的修改,表也是
我這用到的表就兩個字段 id ,msg
var http=require('http');
var qs = require('querystring'); //
var ws=require('ws');
var server=http.createServer(function (req, res) {
res.end("This is a WebSockets server!");
});
var url = require('url');
//驗證函數
function ClientVerify(info) {
var ret = false;//拒絕
//url參數
var params = url.parse(info.req.url, true).query;
//console.log(groupid);
//groupid=params['groupid']
//誰誰誰來到了讨論組
// wss.clients.forEach(function each(client) {
// client.send('233');
// });
return true;
}
var wss = new ws.Server( { server: server,verifyClient: ClientVerify } );
/*//引入資料庫
var mysql = require('mysql');
//連接配接資料庫資訊 普通版
var connection = mysql.createConnection({
host : '1.1.1.1',//資料庫連結
user : 'root',
password : 'root',
database : 'bootdo'
});*/
//引入資料庫
var mysql = require('mysql');
// 建立資料池
const pool = mysql.createPool({
host : '1.1.1.1', // 資料庫位址
user : 'root', // 資料庫使用者
password : 'root', // 資料庫密碼
database : 'bootdo' // 選中資料庫
})
/*接收一個sql語句 以及所需的values
這裡接收第二參數values的原因是可以使用mysql的占位符 '?'
比如 query(`select * from my_database where id = ?`, [1])
好像可以直接使用pool.query,暫時不明*/
let query = function(sql,values,callback){
pool.getConnection(function(err,conn){
if(err){
callback(err,null,null);
}else{
conn.query(sql,values,function(err,results,fields){
//釋放連接配接
conn.release();
//事件驅動回調
callback(err,results,fields);
});
}
});
};
module.exports=query;
wss.on('connection', function connection(ws) {
console.log('連結成功!');
//console.log(ws);
//查詢曆史聊天記錄 廣播給連接配接的用戶端
var sql='select * from hi_test where groupid=1';
console.log('sql語句',sql);
query(sql,function (err,res,fields) {
console.log('sql操作傳回:', res);
if(res!=null){
ws.send(JSON.stringify(res));
}
});
//監聽用戶端發送得消息
ws.on('message', function incoming(data) {
console.log('來自用戶端得message:',data);
//儲存用戶端發送得消息到資料庫
sql="insert into hi_test(msg) values(?)";
console.log('sql語句',sql);
query(sql,data,function (err,res,fields) {
console.log('sql操作傳回:',res);//res.insertId
});
var sendData=JSON.stringify([{msg:data}])
/**
* 把消息發送到所有的用戶端
* wss.clients擷取所有連結的用戶端
*/
wss.clients.forEach(function each(client) {
client.send(sendData);
});
});
});
server.listen(80, function listening() {
console.log('伺服器啟動成功!');
});
/*發起get請求
var options = {
hostname: 'www.tjjxsoft.cn',
path: '/attendanceParameter/getAttendanceParameter/13',
method: 'GET'
};
var req = http.request(options, function (res) {
console.log('狀态: ' + res.statusCode);
res.on('data', function (chunk) {
console.log('傳回資料: ' + chunk);
});
});
req.on('error', function (e) {
console.log('problem with request: ' + e.message);
});
req.end();*/
/*
/!*建構http服務*!/
var app = require('http').createServer()
/!*引入socket.io*!/
var io = require('socket.io')(app);
/!*定義監聽端口,可以自定義,端口不要被占用*!/
var PORT = 80;
/!*監聽端口*!/
app.listen(PORT);
/!*定義使用者數組*!/
var users = [];
/!**
*監聽用戶端連接配接
*io是我們定義的服務端的socket
*回調函數裡面的socket是本次連接配接的用戶端socket
*io與socket是一對多的關系
*!/
io.on('connection', function (socket) {
/!*所有的監聽on,與發送emit都得寫在連接配接裡面,包括斷開連接配接*!/
socket.on('login',function(data){
console.log('有人登入了:')
console.log(data);
users.push({
username:data.username
});
/!*向所有連接配接的用戶端廣播add事件*!/
io.sockets.emit('add',data)
})
})
console.log('app listen at'+PORT);*/
然後指令行輸入node ws.js(你自己的檔案名)回車,就已經啟動了服務
4.現在服務就已經起來了,接下來弄小程式這邊的
直接貼代碼:
wxml:
<view class='homeView'>
<scroll-view scroll-y style="height:500px;" scroll-top='{{scrolltop}}'>
<view class='listView'>
<block wx:for="{{serverMsg}}" wx:key='*this'>
<!-- -->
<view wx:if="{{item.user.id!=userInfo.userId}}" class='leftView'>
<view class='name'>{{item.user.name}}</view>
<view class='imgmsgleft'>
<view>
<!-- 我這用的是自己另一個服務的圖檔 -->
<image class='touimg' src='https://www.tjjxsoft.cn/static/images/img005.png'></image>
</view>
<view>{{item.msg}}</view>
</view>
</view>
<view wx:else class='rightView'>
<view class='name'>{{item.user.name}}</view>
<view class='imgmsg'>
<view>{{item.msg}}</view>
<view>
<!-- 我這用的是自己另一個服務的圖檔 -->
<image class='touimg' src='https://www.tjjxsoft.cn/static/images/img005.png'></image>
</view>
</view>
</view>
</block>
</view>
</scroll-view>
<view class='sendView'>
<input bindinput='sendTextBind' placeholder="輸入聊天内容" value='{{sendText}}' />
<button bindtap='sendBtn' type="primary">發送</button>
</view>
</view>
js:
var app = getApp();
Page({
data: {
socket_open: false,//判斷連接配接是否打開
sendText: "",//發送的消息
serverMsg: [],//接受的服務端的消息
userInfo: { userId: 1, name: "呵呵",img:'頭像'},//app.appData.userInfo,
scrolltop: 999
},
/**輸入内容 */
sendTextBind: function(e) {
this.setData({
sendText: e.detail.value
});
console.log(this.data.sendText);
},
/**發送消息 */
sendBtn: function(e) {
console.log('發送消息事件!');
var msgJson = {
user: {
id: this.data.userInfo.userId,//app.appData.userInfo.userId, //唯一ID區分身份
name: this.data.userInfo.name, //顯示用姓名
img: this.data.userInfo.img, //顯示用頭像
},
msg: this.data.sendText,//發送的消息
groupid:1
}
//發送消息
this.send_socket_message(JSON.stringify(msgJson));
this.setData({
sendText: ""//發送消息後,清空文本框
});
},
onLoad: function(options) {
// app.login();
// this.setData({
// userInfo: app.appData.userInfo
// });
//初始化
this.wssInit();
},
wssInit() {
var that = this;
//建立連接配接
wx.connectSocket({
url: 'ws://localhost'//app.appData.socket
})
//監聽WebSocket連接配接打開事件。
wx.onSocketOpen(function(res) {
console.log('WebSocket連接配接已打開!');
that.setData({
socket_open: true
});
});
//監聽WebSocket接受到伺服器的消息事件。
wx.onSocketMessage(function(res) {
console.log('收到伺服器内容:', res);
var server_msg = JSON.parse(res.data);
console.log(server_msg);
if (server_msg != null) {
var msgnew = [];
for (var i = 0; i < server_msg.length; i++) {
msgnew.push(JSON.parse(server_msg[i].msg));
}
msgnew=that.data.serverMsg.concat(msgnew);
that.setData({
serverMsg: msgnew,
scrolltop: msgnew.length * 100
});
console.log(that.data.serverMsg);
}
});
//監聽WebSocket錯誤。
wx.onSocketError(function(res) {
console.log('WebSocket連接配接打開失敗,請檢查!', res)
});
},
send_socket_message: function(msg) {
//socket_open,連接配接打開的回調後才會為true,然後才能發送消息
if (this.data.socket_open) {
wx.sendSocketMessage({
data: msg
})
}
}
})
wxss:
.homeView {
border-top: 1px solid #ededed;
}
.listView{
padding-bottom: 50px;
}
.listView>view {
padding: 10px;
}
.rightView {
text-align: right;
}
.imgmsgleft {
display: flex;
justify-content: flex-start;
align-items: center;
}
.imgmsgleft>view:last-child {
border: solid 1px gray;
padding: 10px;
border-radius: 6px;
}
.imgmsg {
display: flex;
justify-content: flex-end;
align-items: center;
}
.imgmsg>view:first-child {
border: solid 1px gray;
padding: 10px;
border-radius: 6px;
background-color: green;
}
.touimg {
width: 50px;
height: 50px;
}
.name {
font-size: 14px;
color: gray;
}
.sendView {
display: flex;
width: 100%;
position: fixed;
bottom: 0px;
border-top: 1px #ededed solid;
background-color: white;
}
.sendView>button {
width: 20%;
}
.sendView>input {
width: 80%;
height: auto;
}
效果圖:
預覽的時候一定要打開調試,因為這不是WSS協定,是沒法直接用的