背景
最近有需求要做一个简单业务的 APP 应用,简单考虑选用 uniapp + uview + vue2.x 方案,因为还有web端页面也需要用到 WebSocket ,简单封装了一个适应 web 端的工具,刚开始直接把 web 端的那套代码拿过来用,跑 H5 模式调试在浏览器没有,打包之后问题就出来了,不支持 WebSocket,当时心里咯噔一下,想着这下完了。
冷静下来,百度查一下,原来 uniapp 基于 ECMAScript 扩展了 uni 对象,非 H5 端不支持 window、document、navigator 等浏览器专用对象。uniapp 也实现了 WebSocket ,只是 API 在 uni 对象下。
uni.connectSocket
相关 API 可以直接使用,不过 APP 端所有 vue 页面只能使用一个 websocket 连接。
既然有 API 那就好办了,参考 H5 的封装改改。找了好久,能参考并且比较好的文章不多,那咱也写一段吧。
参考文章
uniapp API 概述
uni.connectSocket API
uni API SocketTask 对象
uni-app框架之如何使用Websocket
uni-app中WebSocket的使用
需求目标
使用 ES6 语法封装一个公用的 WebSocket 类,供组件使用。使用类封装没试过是否可以创建多个 WebSocket 连接,不过 Web 端按照这种方式封装是可以创建多个连接。
实现过程
定义
在 utils 目录,新建一个 websocket.js 文件,定义 WebSocket Class,仔细查看 uniapp 文档,调用 uni.connectSocket
接口可以返回一个 SocketTask 对象,有了这个对象之后,剩下的就是 web 端的差不多了,对象里面支持断开自动重连。
如果需要设置重连延迟时间和重连次数可自行扩展属性,目前是写死在代码中。
注意点:
使用 SocketTask
对象,调用存在时序问题,SocketTask.onOpen 要在 uni.connectSocket
回调调用,不然回调里的内容不会返回。
调用
// index.vue
<script>
import WS from "@/utils/websocket.js"
export default {
//...
data() {
return {
ws: null
}
},
onLoad() {
this.ws && this.ws.closeSocket();
this.ws = new WS(`${process.env.VUE_APP_WS_API}/ws/xxx`) // xxx 表示接口地址URL
// 发送数据
// this.ws.webSocketSendMsg('发送信息')
this.ws.getWebSocketMsg(data => {
const dataJson = data;
console.log('data', dataJson);
if(typeof(dataJson) == "object") {
console.log("wsObject", dataJson);
}else {
console.log(dataJson);
}
});
},
beforeDestroy() {
this.ws && this.ws.closeSocket();
},
//...
}
</script>
主要代码
因为 WebSocket 接收的可能是字符串或对象,又封装了一个类型判断函数文章来源:https://www.toymoban.com/news/detail-406666.html
// @/utils/utils.js
// ...
// 判断字符串是否为JSON格式
export function isJSON(str) {
if (typeof str == 'string') {
try {
var obj = JSON.parse(str);
if (typeof obj == 'object' && obj) {
return true;
} else {
return false;
}
} catch (e) {
// console.log('error:'+str+'!!!'+e);
return false;
}
}
// console.log('It is not a string!')
}
// ...
websocket.js 完整代码文章来源地址https://www.toymoban.com/news/detail-406666.html
// @/utils/websocket.js
import { isJSON } from "@/utils/utils"
class WebSocketClass {
constructor(url) {
this.lockReconnect = false; // 是否开始重连
this.wsUrl = ""; // ws 地址
this.globalCallback = null; // 回调方法
this.userClose = false; // 是否主动关闭
this.createWebSocket(url);
}
createWebSocket(url) {
// #ifdef H5
if (typeof (WebSocket) === 'undefined') {
this.writeToScreen("您的浏览器不支持WebSocket,无法获取数据");
return false
}
// #endif
// #ifdef APP-PLUS
if (typeof (uni.connectSocket) === 'undefined') {
this.writeToScreen("您的浏览器不支持WebSocket,无法获取数据");
return false
}
// #endif
this.wsUrl = url;
try {
// 创建一个this.ws对象【发送、接收、关闭socket都由这个对象操作】
// #ifdef H5
this.ws = new WebSocket(this.wsUrl);
this.initEventHandle();
// #endif
// #ifdef APP-PLUS
this.ws = uni.connectSocket({
url: this.wsUrl,
success(data) {
console.log("websocket连接成功");
this.initEventHandle();
},
});
// #endif
} catch (e) {
this.reconnect(url);
}
}
// 初始化
initEventHandle() {
/**
* 监听WebSocket连接打开成功
*/
// #ifdef H5
this.ws.onopen = (event) => {
console.log("WebSocket连接打开");
};
// #endif
// #ifdef APP-PLUS
this.ws.onOpen(res => {
console.log('WebSocket连接打开');
});
// #endif
/**
* 连接关闭后的回调函数
*/
// #ifdef H5
this.ws.onclose = (event) => {
if (!this.userClose) {
this.reconnect(this.wsUrl); //重连
}
};
// #endif
// #ifdef APP-PLUS
this.ws.onClose(() => {
if (!this.userClose) {
this.reconnect(this.wsUrl); //重连
}
});
// #endif
/**
* 报错时的回调函数
*/
// #ifdef H5
this.ws.onerror = (event) => {
if (!this.userClose) {
this.reconnect(this.wsUrl); //重连
}
};
// #endif
// #ifdef APP-PLUS
this.ws.onError(() => {
if (!this.userClose) {
this.reconnect(this.wsUrl); //重连
}
});
// #endif
/**
* 收到服务器数据后的回调函数
*/
// #ifdef H5
this.ws.onmessage = (event) => {
if(isJSON(event.data)) {
const jsonobject = JSON.parse(event.data)
this.globalCallback(jsonobject)
}else {
this.globalCallback(event.data)
}
};
// #endif
// #ifdef APP-PLUS
this.ws.onMessage(event => {
if(isJSON(event.data)) {
const jsonobject = JSON.parse(event.data)
this.globalCallback(jsonobject)
}else {
this.globalCallback(event.data)
}
});
// #endif
}
// 关闭ws连接回调
reconnect(url) {
if (this.lockReconnect) return;
this.ws.close();
this.lockReconnect = true; // 关闭重连,没连接上会一直重连,设置延迟避免请求过多
setTimeout(() => {
this.createWebSocket(url);
this.lockReconnect = false;
}, 1000);
}
// 发送信息方法
webSocketSendMsg(msg) {
this.ws && this.ws.send({
data: msg,
success() {
console.log("消息发送成功");
},
fail(err) {
console.log("关闭失败", err)
}
});
}
// 获取ws返回的数据方法
getWebSocketMsg(callback) {
this.globalCallback = callback
}
// 关闭ws方法
closeSocket() {
if (this.ws) {
this.userClose = true;
this.ws.close({
success(res) {
console.log("关闭成功", res)
},
fail(err) {
console.log("关闭失败", err)
}
});
}
}
writeToScreen(massage) {
console.log(massage);
}
}
export default WebSocketClass;
记录
- 2022/5/10
改动点:增加条件编译
说明:使用时发现,开发 app 时在浏览器中运行会报错,类似,TypeError: Cannot read properties of undefined (reading ‘onOpen’),在浏览器没有 uni 对象,初始化 socket 失败,需要用 WebSocket,增加条件编译可避免这个问题。
到了这里,关于uniapp APP 端 WebSocket 使用,实现一个简单 WebSocket 工具类的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!