正常的使用场景
- iOS 和安卓都用 webview 配合了同一个页面做的混合应用
- ajax 通过账号从服务器获取包含音频信息的 JSON
- 解析 JSON,从 CDN 预加载音频,添加到 DOM 末尾
- 用户点击按钮 A,播放对应音频 A.mp3
遇见的 BUG
极个别用户在点击按钮 A 的时候,播放的音频是另外一个页面按钮 B 的音频 B.mp3。
已知的信息
- 音频播放的页面有十多个音频,出现错乱的只有两个
- 播放出来错乱的音频不属于这个页面,这个用户之前也不可能播放过
- 清除缓存,更新应用没有帮助
- 将表现正常的账号给用户登录之后,用户的机器上也能稳定复现
- iOS 和安卓都能稳定复现,错误表现相同
- 只有音频内容错乱,其他内容是正常的。
个人看法
如果是服务器分发 JSON 有误,那么应该是整个数据都会错乱,为什么只有音频内容出错了呢?
我知道这个想法很蠢,但是会不会 CDN 分发了错误的音频数据。。。
关键代码
音频预加载:
preload(id, src) {
return new Promise((resolve, reject) => {
const check = document.querySelector('#' + this.format(id))
if (check) {
// console.warn('[preloadAudio] Can NOT preload', id, 'because there\'s already one.')
} else {
const x = document.createElement("AUDIO")
x.setAttribute("preload", "auto")
x.setAttribute("id", this.format(id))
x.setAttribute("src", src + id)
x.setAttribute("canplay", "0")
document.body.appendChild(x)
x.addEventListener('canplay', () => {
x.setAttribute("canplay", "1")
resolve()
}, false)
x.addEventListener('onerror', () => {reject()}, false)
}
})
}
format
用于格式化:
format(str) {
return str.replace(/[-, ,’,.]/g,'_').toLowerCase()
}
下面是播放:
playAudio(id) {
const x = document.querySelector('#' + this.format(id))
x.play()
}
和用户确认了,是CDN分发了错误的音频数据。
同一个链接我这里听是正常的,用户从 app 和 Safari 里面听到都是错误的。