美文网首页
websocket 语音推送及重连机制

websocket 语音推送及重连机制

作者: McDu | 来源:发表于2021-02-22 16:33 被阅读0次
    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);
    
    

    相关文章

      网友评论

          本文标题:websocket 语音推送及重连机制

          本文链接:https://www.haomeiwen.com/subject/gslkfltx.html