Uniapp如何全局使用websocket
此教程基于uniapp提供的uniapp-tools的socket.js插件1.创建socket.js(封装好的websocket连接对象)const noop = function() {};class Socket {static stopTime = 0;static concatCount = 0;constructor({url = '',onOpen = noop,onMsg = no
·
此教程基于uniapp提供的uniapp-tools的socket.js插件
1.创建socket.js(封装好的websocket连接对象)
const noop = function() {};
class Socket {
static stopTime = 0;
static concatCount = 0;
constructor({
url = '',
onOpen = noop,
onMsg = noop,
onClose = noop,
onError = noop,
onReload = noop,
onRdFinsh = noop,
maxInterValCount = 10,
interValTime = 2000,
SocketState = {},
...args
} = {}) {
this.isRconnectIng = false; //是否处于重连状态
this.waiting = Promise.resolve(false); //心跳检查必须等待重连完成后
this.waitDep = []; //等待时收集依赖的容器
this.SocketTask = {
nsend: noop,
nclose: noop,
nrconnect: noop,
isconnect: false,
uniColse: false,
maxInterValCount,
interValTime,
InterValCount: 0,
eventPatch: null,
url,
onOpen,
onMsg,
onClose,
onError,
onReload,
onRdFinsh,
extra: args
};
this._EventDispath(this.SocketTask);
this.initChat(this.SocketTask, this.SocketTask.extra);
return this.SocketTask;
}
set CONCATCOUNT(value) {
Socket.concatCount = value;
if (value > 0) this._notify();
}
get CONCATCOUNT() {
return Socket.concatCount
}
/**
* 仅供内部使用,通知所有收集到的依赖
*/
_notify() {
for (let i = 0; i < this.waitDep.length; i++) {
this.waitDep[i].call(this.SocketTask);
}
this.waitDep = [];
}
/**
* 仅供内部使用,确认当前是否连接成功,收集依赖
*/
_chunkConnect(fn) {
if (Socket.concatCount > 0) {
fn();
} else {
this.waitDep.push(fn);
}
}
/**
* 仅供内部使用,事件注册
*/
_EventDispath({
onReload
} = {}) {
let SocketTask = this.SocketTask;
let events = {
onOpen: [],
onMsg: [],
onClose: [],
onError: [],
onReload: [],
onRdFinsh: [],
}
SocketTask.nsend = text => {
this._chunkConnect(() => {
uni.sendSocketMessage({
data: text
})
})
}
SocketTask.nclose = t => {
this._chunkConnect(() => {
SocketTask.uniColse = true;
uni.closeSocket();
})
}
SocketTask.nrconnect = t => {
this._chunkConnect(() => {
this.waiting = new Promise(async (resolve) => {
uni.closeSocket();
let reloadStatus = false;
try {
const res = await this.initChat(SocketTask, SocketTask.extra);
reloadStatus = res;
} catch (e) {}
onReload.call(SocketTask, reloadStatus, SocketTask);
SocketTask.eventPatch.dispatchEvent('onReload', reloadStatus);
resolve(reloadStatus);
})
})
}
function EventDispatcher() {
this.events = events;
}
for (let key in events) {
EventDispatcher.prototype[key] = function(handler) {
if (typeof handler != 'function') return;
this.events[key].push(handler)
}
}
EventDispatcher.prototype.dispatchEvent = function(type, msg) {
let evenArr = this.events[type];
if (evenArr.length > 0) {
for (let i = 0; i < evenArr.length; i++) {
evenArr[i].call(SocketTask, msg, SocketTask);
}
}
}
SocketTask.eventPatch = new EventDispatcher();
}
/**
* 心跳检测
*/
async hbDetection() {
const SocketTask = this.SocketTask;
if (SocketTask.uniColse) {
return false;
}
clearTimeout(Socket.stopTime);
if (!SocketTask.isconnect) { //未连接则启动连接
if (SocketTask.maxInterValCount > SocketTask.InterValCount) {
Socket.stopTime = setTimeout(async () => {
try {
const R_result = await this.waiting;
if (R_result) return;
this.isRconnectIng = true;
const openResult = await this.initChat(SocketTask, SocketTask.extra);
if (openResult) return;
SocketTask.InterValCount++;
return this.hbDetection();
} catch (e) {
return this.hbDetection();
}
}, SocketTask.interValTime)
} else {
SocketTask.onRdFinsh.call(SocketTask, SocketTask.maxInterValCount, SocketTask);
SocketTask.eventPatch.dispatchEvent('onRdFinsh', SocketTask.maxInterValCount);
}
}
}
/**
* websocket监听事件
*/
SocketEvents({
onOpen,
onMsg,
onClose,
onError,
onReload,
} = {}) {
return new Promise((resolve, reject) => {
const SocketTask = this.SocketTask;
uni.onSocketOpen(res => {
this.CONCATCOUNT += 1;
this.isRconnectIng = false;
SocketTask.isconnect = true;
SocketTask.InterValCount = 0;
SocketTask.uniColse = false;
resolve(true);
onOpen.call(SocketTask, res, SocketTask);
SocketTask.eventPatch.dispatchEvent('onOpen', res)
})
uni.onSocketMessage(msg => {
onMsg.call(SocketTask, msg, SocketTask);
SocketTask.eventPatch.dispatchEvent('onMsg', msg)
})
uni.onSocketClose(async err => {
SocketTask.isconnect = false;
resolve(false);
if (!this.isRconnectIng) {
this.hbDetection();
onClose.call(SocketTask, err, SocketTask);
SocketTask.eventPatch.dispatchEvent('onClose', err);
}
})
uni.onSocketError(err => {
uni.closeSocket();
onError.call(SocketTask, err, SocketTask);
SocketTask.eventPatch.dispatchEvent('onError', err)
})
})
}
/**
* 开始初始化chat
*/
initChat({
url,
onOpen,
onMsg,
onClose,
onError,
onReload
} = {}, args) {
return new Promise(async (resolve, reject) => {
try {
await this.connectSocket(url, args);
let res = await this.SocketEvents({
onOpen,
onMsg,
onClose,
onError,
onReload,
})
resolve(res);
} catch (e) {
console.log(e)
reject();
}
})
}
/**
* 连接webSocket
*/
connectSocket(url, args) {
return new Promise((resolve, reject) => {
uni.connectSocket({
url,
success: () => {
resolve();
},
fail: err => {
reject();
},
...args
})
})
}
}
export default Socket
2.创建useWebSocket.js
import Vue from 'vue'
import store from "./index.js"; //引入vuex,引入自己的路径
import socket from "../store/socket.js"; //引入socket.js,引入自己的路径
//这里将socket.js中的创建连接和接受消息的监听放到一个可以向外部暴露的方法,方便在合适的时机创建websocket连接
export function connectWebSocket(){
const Socket =new socket({
url: 'ws://127.0.0.1:8086/ws', //连接地址 必填
onOpen(res) {
console.log('连接成功')
},
onClose(err) {
console.log('关闭了连接')
},
onReload(res) {
console.log('重载:' + res)
},
onMsg(msg) {
console.log(msg)
}
});
//加入监听,就可以全局使用监听了
Socket.eventPatch.onOpen((msg,sk)=>{ //监听是否连接成功
});
Socket.eventPatch.onMsg((msg,sk)=>{ //监听是否接受消息
console.log(msg)
});
Vue.prototype.$Socket = Socket; //连接成功挂在到原型上
}
3.修改 main.js
import Vue from 'vue'
import App from './App'
import store from '@/store' //引入自己的路径
import './store/useSocket.js' //引入自己的路径
Vue.prototype.$store=store
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
4.修改vuex的js文件index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store =new Vuex.Store({
state: {
SocketState: {},
SocketStateErr: {},
},
mutations:{
setSocketState(that, info) {
that.SocketState = info
},
setSocketStateErr(that, info) {
that.SocketStateErr = info;
}
},
})
export default store
5.案例
1)Login.vue登录页面,主要看登录的实现
<template>
<view>
<h3>登录页</h3>
<div>
<view class="uni-padding-wrap uni-common-mt" style="padding:20px">
<view class="button-sp-area">
<button type="primary" plain="true" @click="login('/pages/main/message/message')">登录</button>
</view>
</view>
</div>
</view>
</template>
<script>
import {connectWebSocket} from "../../store/useSocket.js"; //引入socket.js 重要
export default {
methods: {
login(url){
connectWebSocket();
var mobile="123456";
//在跳转其他页面之前判断是否成功连接websocket
this.$Socket.eventPatch.onOpen((msg,sk)=>{ //监听是否连接成功
console.log('连接成功')
//关闭其他页面,进入url页面
uni.reLaunch({
url:url+"?mobile="+mobile
})
this.$Socket.nsend(mobile)
});
}
}
}
</script>
2)message.vue
<template>
<view>
<div>
<view class="uni-padding-wrap uni-common-mt" style="padding:20px">
<view class="uni-form-item uni-column">
<view class="title">收到的消息内容</view>
<input class="uni-input" type="text" placeholder="xxx:xxxxx" :disabled="true" v-model="console" />
</view>
<br>
<view class="uni-form-item uni-column">
<view class="title">请输入朋友ID</view>
<input class="uni-input" type="text" required placeholder="xxx" v-model="friendId" />
</view>
<br>
<view class="uni-form-item uni-column">
<view class="title">输入发送内容</view>
<input class="uni-input" required placeholder="这个周日你有空吗" v-model="message" />
</view>
<br>
<view class="button-sp-area">
<button type="primary" plain="true" @click="sendMessage()">发送</button>
</view>
</view>
</div>
</view>
</template>
<script>
export default {
data() {
return {
myId:'',
friendId:'',
message:'',
console:''
}
},
onLoad(obj){
this.$data.myId=obj.mobile;
},
onShow(){
//页面渲染之后触发监听消息接收
this.onmessage();
},
methods: {
onmessage(){
//当websocket收到后端发送的消息时,触发
this.$Socket.eventPatch.onMsg((msg,sk)=>{ //监听是否接受消息
var backMessage=msg.data.split(":");
this.console="来自你的好友:"+backMessage[0]+","+"发来的消息:"+backMessage[1];
});
},
sendMessage(){
var mess=this.myId+","+this.friendId+","+this.message;
//通过已经在登录页建立好的为websocket连接向后端发送消息
this.$Socket.nsend(mess);
}
}
}
</script>
<style>
</style>
更多推荐
已为社区贡献1条内容
所有评论(0)