如何修复SoundCloud widget API抛出的Uncaught (in promise) DOMException错误
SoundCloud Widget API 未捕获请求中止错误修复方案
错误根因
你遇到的报错是连续调用seekTo和play两个异步操作时,前一个请求还未完成就被后一个操作中断,同时旧版SoundCloud Widget API未对部分异步方法暴露Promise catch回调,未捕获的异常直接抛到全局导致播放器卡死。
可落地修复步骤
- 第一步:给进度条事件加防抖,避免拖动进度条时高频触发
seekTo产生大量并发中断请求 - 第二步:加操作状态锁,避免前一次播放器操作未完成就触发下一次操作
- 第三步:用
Promise.resolve包装API调用,统一捕获异步异常,避免异常抛到全局
修复后代码示例
// 定义操作锁,避免并发调用播放器方法 let isOperating = false // 防抖函数,可根据实际交互体验调整间隔时间(100-500ms) const debounce = (func, wait = 300) => { let timer return function(...args) { clearTimeout(timer) timer = setTimeout(() => func.apply(this, args), wait) } } $(scrubber).on('click input', debounce((e) => { e.preventDefault() if (isOperating) return isOperating = true try { // 包装seekTo调用,捕获中断异常 Promise.resolve(widget.seekTo(e.target.value)) .catch(err => console.warn('seek操作中止,可忽略:', err)) .finally(() => { // 等待seek操作完成后再调用play return Promise.resolve(widget.play()) .catch(err => console.warn('play操作中止,可忽略:', err)) .finally(() => { isOperating = false // 原有UI更新逻辑不变 $('#pauseSongIcon').show(); $('#playSongIcon').hide(); $('#playbackIconPause').show(); $('#playbackIconPlay').hide(); animatePlayback(); }) }) } catch (err) { // 捕获同步抛出的异常 isOperating = false console.warn('播放器操作异常,可忽略:', err) } }))
降级兼容方案
如果你的项目需要兼容不支持Promise的老旧环境,直接用延时错开两个方法的调用即可:
$(scrubber).on('click input', debounce((e) => { e.preventDefault() widget.seekTo(e.target.value) // 延时150ms调用play,避免两个操作同时触发中断 setTimeout(() => { widget.play() }, 150) $('#pauseSongIcon').show(); $('#playSongIcon').hide(); $('#playbackIconPause').show(); $('#playbackIconPlay').hide(); animatePlayback(); }))
内容的提问来源于stack exchange,提问作者freelanceing mindset
相关产品推荐
相关产品推荐

