本文章只是小弟在开发过程中所做的需求,踩坑过顺便写个博客用来做下笔记,如果代码有什么不足之处,希望大佬们指出,谢谢!
感觉能解决了问题的,动动小指头点个赞~ O(∩_∩)O
** 1.此处说下我的需求:是通过websocket接受后端传递的数据,赋值到input输入框,然后再进行一系列的操作,如果websocket链接失败则弹窗提示,并且无限建立心跳链接,不允许断开。废话不多直接代码截图,本demo引入uview库,需要demo在文章末尾会写链接。**
websocket主要步骤:使用uniapp官网提供的API建立websocket链接,进入连接监听,在失败的监听中设置定时器定时去发送连接,直到服务器连接成功,写的过程中踩的坑莫名其妙,忘了如何描述,如果哪里写得不好请指点,第一次写。
1、以下是html 调用的示例,代码删除了许多无关代码,只需要看调用方法就行了。
<template>
<view class="container">
<!-- 需求:通过websocket实时获取数据,赋值到输入框 ,如果websocket链接失败则弹窗警告-->
<view class="content-left">
<!-- 扫描条码 -->
<view class="textFontSize scan-container">
<view class="mr-2 color-red font-w-b" style="font-size: 35rpx;">扫描条码:</view>
<view class="scanBox flex-1 mr-1">
<input class="flex-1 pl-2" type="text" confirm-type="search" placeholder="请扫描载具条码" v-model="scanCode"/>
</view>
<view class="scan-btn">
<text class="iconfont icon-dagou"></text>
<text class="ml-2">扫描提交</text>
</view>
</view>
</view>
<!-- websocket连接失败弹窗 -->
<u-mask :show="socketShow" >
<view class="warp">
<u-tag :text="webtext" mode="dark" class="warp-tag" type="error"/>
</view>
</u-mask>
</view>
</template>
<script>
import { websocetObj } from '@/utils/websocet/websocet.js';
export default {
data() {
return {
socketShow:false,
webtext:'',
}
},
methods: {
//websocet函数回调:返回监听的数据
getWebsocetData(val){
// val = String.fromCharCode.apply(null, new Uint8Array(val)).trim() 如果后端返回数据格式是其他的,可能需要转换一下,比如这个,应该是转Unicode编码
console.log(val,'函数回调');
this.scanCode = val;
},
//websocet函数抛错: 返回错误信息 用于用户提示
getWebsocetError(err){
this.socketShow = err.isShow;
this.webtext = err.messge;
console.log('websocet函数抛错',this.socketShow);
},
//websocet函数成功进入: 监听连接状态,在失败的时候弹窗提示,具体需求看自身情况
onErrorSucceed(val){
this.socketShow = val.isShow;
console.log('websocet函数成功进入',this.socketShow);
}
},
mounted() {
},
onLoad() {
// 在onload的时候调用,创建webscoet连接对象,参数分别为:url、获取后端返回数据、监听websocket的链接失败返回的报错、监听链接状态,返回布尔值
websocetObj.sokcet('ws://192.168.xxxx',this.getWebsocetData,this.getWebsocetError,this.onErrorSucceed)
},
//离开页面销毁websocket
beforeDestroy() {
websocetObj.stop();
},
}
</script>
2、以下是JS封装的代码
let isSocketClose=false; // 是否关闭socket
let reconnectCount=5; // 重连次数
let heartbeatInterval=""; // 心跳定时器
let socketTask = null; // websocket对象
let againTimer = null;//断线重连定时器
let url = null;
let onReFn = null;
let onSucFn = null;
let onErrFn = null;
/**
* sockeUrl:websocet的地址
* onReceive:消息监听的回调
* onErrorEvent:抛出错误的回调,且弹窗连接失败的提示框
* onErrorSucceed:抛出成功回调,主要用于隐藏连接失败的提示框
* */
const sokcet= (sockeUrl,onReceive,onErrorEvent,onErrorSucceed)=> {
url = sockeUrl;
onReFn= onReceive;
onErrFn= onErrorEvent;
onSucFn= onErrorSucceed;
isSocketClose=false;
//判断是否有websocet对象,有的话清空
if(socketTask){
socketTask.close();
socketTask = null;
clearInterval(heartbeatInterval);
}
//WebSocket的地址
// 【非常重要】必须确保你的服务器是成功的,如果是手机测试千万别使用ws://127.0.0.1:9099【特别容易犯的错误】
let url = sockeUrl
// 连接
socketTask = uni.connectSocket({
url: url,
success(data) {
console.log("websocket连接成功");
clearInterval(againTimer)//断线重连定时器
},
fail: (err) => {
console.log("报错",err);
}
});
// 连接打开
socketTask.onOpen((res)=>{
console.log('WebSocket打开');
clearInterval(againTimer)//断线重连定时器
onErrorSucceed({isShow:false}) // 用于提示框的隐藏
heartbeatInterval && clearInterval(heartbeatInterval);
// 10秒发送一次心跳
heartbeatInterval = setInterval(() => {
sendMsg('心跳ing')
}, 1000*5)
})
// 监听连接失败
socketTask.onError((err)=>{
console.log('WebSocket连接打开失败,请检查',err);
//停止发送心跳
clearInterval(heartbeatInterval)
//如果不是人为关闭的话,进行重连
if (!isSocketClose) {
reconnect(url,onErrorEvent)
}
})
// // 监听连接关闭 -
socketTask.onClose((e) => {
console.log('WebSocket连接关闭!');
clearInterval(heartbeatInterval)
if (!isSocketClose) {
reconnect(url,onErrorEvent)
}
})
// 监听收到信息
socketTask.onMessage((res) => {
uni.hideLoading()
console.log(res,'res监听收到信息')
let serverData = res.data
//与后端规定好返回值分别代表什么,写业务逻辑
serverData && onReceive(serverData);
});
}
const reconnect = (url,onErrorEvent)=>{
console.log('进入断线重连',isSocketClose);
clearInterval(againTimer)//断线重连定时器
clearInterval(heartbeatInterval);
socketTask && socketTask.close(); // 确保已经关闭后再重新打开
socketTask = null;
onErrorEvent({isShow:true,messge:'扫描头服务正在连接...'})
// 连接 重新调用创建websocet方法
againTimer = setInterval(()=>{
sokcet(url,onReFn,onErrFn,onSucFn)
console.log('在重新连接中...');
},1000*5)
}
const sendMsg = (msg)=>{ //向后端发送命令
msg = JSON.stringify(msg)
try{
//通过 WebSocket 连接发送数据
socketTask.send({
data: msg
});
}catch(e){
if(isSocketClose){
return
}else{
reconnect(url,onErrFn)
}
}
}
// 关闭websocket【必须在实例销毁之前关闭,否则会是underfined错误】beforeDestroy() {websocetObj.stop();}
const stop = ()=>{
isSocketClose = true
clearInterval(heartbeatInterval);
clearInterval(againTimer)//断线重连定时器
socketTask.close(); // 确保已经关闭后再重新打开
socketTask = null;
}
export const websocetObj = {
sokcet,
stop,
sendMsg
};
本文章的demo案例链接(里面包含了uniapp在线预览pdf的操作,只查看websocket就行了):https://gitee.com/ZhouLoveBrother/uniapp-websocket-pdf。
关于uniapp app 在线预览pdf文章:https://blog.csdn.net/ZhouLoverBrother/article/details/111148025