Websocket问题记录
提取ws公共方法
会涉及多次创建和取消ws,所以就提取出来,通过mixin方式引入
// /mixins/socket.js
<script>
export default {
name: "socket",
methods: {
sleep(){
return new Promise(resolve => setTimeout(resolve, 100))
},
linkWs (type, wsUrl) {
this.tryStartWs(type, wsUrl)
this.$on('logout', () => {
if (this[type + 'Socket']) {
console.log('close camera socket')
this.closeWs()
}
})
this.$on('login', () => {
console.log('start ws call by login')
this.tryStartWs(type, wsUrl)
})
},
// 尝试ipPorts是否能够成功创建ws
tryStartWs(type, wsUrl) {
if (this[type + 'Socket']) {
console.log('tryStartWs: ws camera close')
this.closeWs()
}
return Promise.race([wsUrl].map(url => {
return this.testWsUrl(url)
})).then(({code, data})=> {
if (code === 1) {
this.wsUrl = data
console.log('start ws camera at: ', this.wsUrl)
// this.ctaSocket = new WebsocketHeartbeat({url: this.wsCtaUrl})
this[type + 'Socket'] = new WebSocket(this.wsUrl)
this[type + 'Socket'].onmessage = this.onWsMessage
this[type + 'Socket'].onopen = () => {
this.onInitSend('type')
}
return this[type + 'Socket']
}
return new Error('start ws failed: can not connect', code, data)
})
},
testWsUrl(url, payload = 5000) {
let timer = exec => setTimeout(exec, payload)
return new Promise((res) => {
// let socket = new WebsocketHeartbeat({url})
let socket = new WebSocket(url)
socket.onopen = function () {
socket.close()
res({code: 1, data: url})
}
socket.onintialfailed = function (err) {
// console.log('intailFialed--->', err)
socket.close()
// 保证失败的时候时间至少是payload
timer(() => {
res({code: -1, data: err})
})
}
socket.onerror = function (err) {
// console.log('onerror-->', err)
socket.close()
// 保证失败的时候时间至少是payload
timer(() => {
res({code: -2, data: err})
})
}
})
},
closeWs(type) {
let socket = this[type + 'Socket']
if (socket) {
socket.close()
socket = null
}
}
}
}
</script>
ws引入
// index.vue
import socket from "@/mixins/socket";
export default {
mixins: [socket],
created() {
this.linkWs('upload', 'ws://192.168.5.201:8080/ws/communication/upload')
},
methods: {
onInitSend () {
},
onWsMessage(params) {
console.log('receive:', data)
}
},
beforeDestroy() {
this.closeWs('upload')
}
}
</script>
连接到ws时,需要一次性多次send,如果不加sleep间隔的话,会把后端的服务器干崩
及时断开ws连接,后端的ws连接数上限也会有问题
通过ws上传文件
onUpdate(obj) {
let file = obj.file
console.log(file)
const reader = new FileReader();
reader.readAsArrayBuffer(file);//以二进制形式读取文件
//文件读取完毕后该函数响应
reader.onload = async (evt) => {
// let ext = file.name.split(".")[1];
// console.log(ext)
this.uploadSocket.send(`set/upgrade=${file.name}`)
let blob = evt.target.result;
await this.sleep()
this.uploadSocket.send(blob);
console.log("finish");
}
}
上传约定方法是先发送这次是什么类型,并告知文件名称,再传输文件
下载ws传输文件
onWsMessage(params) {
let data = params.data
if (typeof data === 'string') {
this.logName = data
} else {
let a = document.createElement('a')
let blob = new Blob([data], {type: 'application/zip'})
let url = window.URL.createObjectURL(blob)
a.setAttribute('download', this.logName)
a.href = url
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
window.URL.revokeObjectURL(url)
}
}
const data = fs.readFileSync('yarn-error.log'); client.send(data);
wfs.js处理h264裸流
<video ref="video" id="video" controls></video></div>
this.$nextTick(() => {
if (Wfs.isSupported()) {
this.wfs = new Wfs()
this.wfs.attachMedia(this.$refs.video,'ch1')
}
})
// 断开
this.wfs.destory()
需要注意的是在该库中直接修改ws地址
key: 'onMediaAttached',
value: function onMediaAttached(data) {
console.log(data)
if (data.websocketName != undefined) {
var client = new WebSocket('ws://192.168.5.201:8080/ws/communication/h264video');
this.wfs.attachWebsocket(client, data.channelName);
} else {
console.log('websocketName ERROE!!!');
}
}
The play() request was interrupted by a call to pause().
Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause(). 在使用wfs.js库的时候,部分浏览器出现了该问题。
我看大部分的解决方案是
this.media.load()
let playPromise = this.media.play()
if (playPromise !== undefined) {
playPromise.then(_ => {
this.media.play();
})
.catch(error => {
console.log(error)
});
}
但还是没解决问题,加了load后反而会报错。