websocket 语音推送及重连机制
2021-02-22 本文已影响0人
McDu
let audioMap = {
test1: '//xxx.mp3',
test2: '//xxx.mp3',
test3: '//xxx.mp3',
test4: '//xxx.mp3'
};
let audioArr = [];
let rePlay = false;
let ws;
let lockReconnect = false; // 避免重复连接
let wsUrl = window.location.href.replace(/^http(s?:\/\/(.*?))\/.*$/, 'ws$1/ws/voice/remind.json');
function createWebSocket(url) {
try {
ws = new WebSocket(url);
initEventHandle();
} catch (e) {
reconnect(url);
}
}
function initEventHandle() {
ws.onclose = function() {
reconnect(wsUrl);
};
ws.onerror = function() {
reconnect(wsUrl);
};
ws.onopen = function() {
ws.send('hello start!');
// 心跳检测重置
heartCheck.reset().start();
};
ws.onmessage = function(event) {
// 如果获取到消息,心跳检测重置
// 拿到任何消息都说明当前连接是正常的
heartCheck.reset().start();
let data = JSON.parse(event.data);
audioArr.length == 0 && (rePlay = true);
if (data && data.length) {
let newData = data.map(function(item) {
return {
url: audioMap[item.voice_key],
priority: item.priority
};
});
audioArr = audioArr.concat(newData);
audioArr.sort(function(a, b) {
return a.priority - b.priority;
});
rePlay && firstRender();
}
};
}
function reconnect(url) {
if (lockReconnect) return;
lockReconnect = true;
// 没连接上会一直重连,设置延迟避免请求过多
setTimeout(function() {
createWebSocket(url);
lockReconnect = false;
}, 60000);
}
// 心跳检测
let heartCheck = {
timeout: Math.floor(Math.random() * (90000 - 30000) + 30000),
timeoutObj: null,
serverTimeoutObj: null,
reset: function() {
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
return this;
},
start: function() {
let self = this;
this.timeoutObj = setTimeout(function() {
// 发送一个心跳,后端收到后,返回一个心跳消息,onmessage拿到返回的心跳就说明连接正常
ws.send('HeartBeat');
// 如果超过一定时间还没重置,说明后端主动断开了
self.serverTimeoutObj = setTimeout(function() {
// 如果直接执行reconnect 会触发onclose导致重连两次
ws.close();
}, self.timeout);
}, this.timeout);
}
};
let firstRender = function() {
let oldAudio = document.getElementsByTagName('audio');
if (oldAudio.length) {
document.body.removeChild(oldAudio[0]);
}
let audio = new Audio();
let playEndedHandler = function() {
if (!audioArr.length) {
return;
}
audio.src = audioArr.length && audioArr.shift().url;
audio.play();
};
audio.preload = true;
audio.autoplay = false;
audio.src = audioArr.length && audioArr.shift().url;
audio.addEventListener('ended', playEndedHandler, false);
document.body.appendChild(audio);
audio.muted = true;
try {
let isplay = audio.play();
if (isplay !== undefined) {
isplay.then(function() {
audio.muted = false;
audio.pause();
setTimeout(function() {
audio.play();
}, 100);
}).catch(function(e) {
audioArr = [];
console.log(e);
});
}
} catch (e) {
audioArr = [];
console.log(e);
}
audio.loop = false;
rePlay = false;
};
createWebSocket(wsUrl);