策略詳情
媒體參與度
AudioContext音頻API的實現
new Audio音頻API的實現
相關實踐
網頁端
使用new Audio創建的音頻對象進行音頻播放的時候,如果用戶沒有與頁面進行交互,那么會報錯如下:
使用AudioContext創建的對象播放音頻,不會報錯,但是會有警告如下:
以上報錯都是在用戶與頁面交互前,創建音頻對象的時候報錯。我們通過websocket推送的音頻消息,只要用戶沒有與頁面有交互,都不會進行播放。直到用戶點擊了頁面,與頁面進行了交互,我們后續的websocket音頻消息才能正常播放。
釘釘桌面端
我們將我們的H5應用集成到釘釘桌面端,在網頁端出現的無交互不播放的問題,在釘釘桌面端不存在。
但是釘釘桌面端又存在其他問題。
(1)釘釘桌面端掛后臺定時任務放緩
由于收到節能機制影響,導致ws斷線重連的時候延遲到2分鐘后才發起重連
我們使用web worker可以繞開節能機制的影響
// timer-worker.js
let timers = {};self.onmessage = function(e) {const { type, id, delay } = e.data;switch(type) {case 'setInterval':timers[id] = setInterval(() => {postMessage({ type: 'interval', id });}, delay);break;case 'setTimeout':timers[id] = setTimeout(() => {postMessage({ type: 'timeout', id });delete timers[id];}, delay);break;case 'clearInterval':case 'clearTimeout':if (timers[id]) {clearInterval(timers[id]);clearTimeout(timers[id]);delete timers[id];}break;}
};
// timer-worker-class.js
class WorkerTimer {constructor() {this.worker = new Worker('resources/central/common/timer-worker.js');this.callbacks = {};this.currentId = 0;this.worker.onmessage = (e) => {const { type, id } = e.data;if (this.callbacks[id]) {this.callbacks[id]();if (type === 'timeout') {delete this.callbacks[id];}}};}setInterval(callback, delay) {const id = ++this.currentId;this.callbacks[id] = callback;this.worker.postMessage({ type: 'setInterval', id, delay });return id;}setTimeout(callback, delay) {const id = ++this.currentId;this.callbacks[id] = callback;this.worker.postMessage({ type: 'setTimeout', id, delay });return id;}clearInterval(id) {if (this.callbacks[id]) {this.worker.postMessage({ type: 'clearInterval', id });delete this.callbacks[id];}}clearTimeout(id) {if (this.callbacks[id]) {this.worker.postMessage({ type: 'clearTimeout', id });delete this.callbacks[id];}}}
項目代碼中使用如下
workerTimer:new WorkerTimer(),vm.workerTimer.clearInterval(vm.heartbeatTimer);vm.workerTimer.setInterval
如上確實解決了定時任務放緩的問題。
(2)釘釘桌面端掛后臺聲音積壓和聲音丟失
釘釘桌面端最小化的時候,等待2分鐘后派單,無聲音播報,若立馬切前臺,會發出語音(如果派單了多條,那么此時會同時發出多條語音)。若等待時間較久,那么語音會丟失。
且切換前臺的時候,websocket的onmessage回調方才執行。
問題在咨詢釘釘專家團隊,尚未解決。
(3)釘釘桌面端掛前臺websocket三分鐘一斷開
通過添加心跳協議解決該問題,同時保證斷線重連。websocket代碼如下:
isConnecting:false,heartbeatInterval:30000,heartbeatTimer:null,reconnectInterval:300,setNoticeSocket(time){let vm = this;console.log("重連setNoticeSocket",vm.isConnecting,'new Date()',new Date(),'time-notifyConnetTime',time);if(vm.isConnecting){return;}if (typeof (WebSocket) == "undefined"){console.log("current web client is not support for websocket.")} else {let host = window.location.host;let scheme = window.location.protocol;let ws = 'ws://' + host;if (scheme.toLowerCase() == 'https:'){ws = 'wss://' + host;}let name= JSON.parse(localStorage.getItem('user')).user.replace(/\\/g,"*");let url = '/central/notify/refresh/'+name;console.log("重連newwebsocket前",new Date(),'vm.noticeSocket',vm.noticeSocket,'vm.noticeSocket.readyState',vm.noticeSocket && vm.noticeSocket.readyState)if(!vm.noticeSocket || (vm.noticeSocket && vm.noticeSocket.readyState === WebSocket.CLOSED)){console.log("重連newwebsocket",new Date(),'vm.noticeSocket.readyState',vm.noticeSocket && vm.noticeSocket.readyState,'time--notifyConnetTime',time)vm.isConnecting = true;vm.noticeSocket = new WebSocket(ws+url);vm.noticeSocket.onopen = function () {console.log("重連成功onopen",new Date())vm.isConnecting = false;vm.notifyConnetTime = 0;let data = {use:"FILTER",perspective:localStorage.getItem('perspective'),status: "0",id:'READ'};vm.noticeSocket.send(JSON.stringify(data))vm.heartbeatTimer && vm.workerTimer.clearInterval(vm.heartbeatTimer);vm.heartbeatTimer = vm.workerTimer.setInterval(() => {if (vm.noticeSocket.readyState === WebSocket.OPEN) {vm.noticeSocket.send(JSON.stringify({ type: 'heartbeat' }));}}, vm.heartbeatInterval);};vm.noticeSocket.onmessage = function (message) {let res = message.data;console.log("接收到ws消息----",res,new Date())if(!res) return;try{let data = JSON.parse(res);}catch(err){}};vm.noticeSocket.onclose = function (message) {vm.isConnecting = false;vm.heartbeatTimer && vm.workerTimer.clearInterval(vm.heartbeatTimer);vm.heartbeatTimer = null;vm.reconnetNotice('來自close');};vm.noticeSocket.onerror = function (message) {vm.isConnecting = false;vm.heartbeatTimer && vm.workerTimer.clearInterval(vm.heartbeatTimer);vm.heartbeatTimer = null;vm.noticeSocket.close();};}}},reconnetNotice(type){let vm = this;console.log("reconnetNotice-發起重連type",type,vm.notifyConnetTime,'new Date()',new Date())// if(vm.notifyConnetTime<20){vm.workerTimer.setTimeout(()=>{vm.notifyConnetTime=vm.notifyConnetTime +1;console.log("重連執行--vm.notifyConnetTime",type,vm.notifyConnetTime,'date',new Date())vm.setNoticeSocket(vm.notifyConnetTime)},vm.reconnectInterval)// }return;},
(4)釘釘桌面端掛后臺websocket五分鐘一斷開
問題在咨詢釘釘專家團隊,尚未解決。