Expo-AV Playback类unloadAsync方法执行成功但抛出TypeError错误的解决方法咨询
解决Expo-AV Audio.Sound卸载时的
TypeError: this._eventEmitter.removeSubscription is not a function错误 这个错误我之前排查过,大多是音频实例的内部状态异常导致的——要么是调用unloadAsync时实例已经被部分清理,要么是异步加载的流程没处理好,组件卸载时操作了无效的sound实例。结合你的代码,给你几个可行的解决方案:
1. 修正异步加载与清理的流程控制
你原代码用then回调赋值soundHandler,但组件可能在音频加载完成前就卸载,或者清理函数执行时实例状态不稳定。改成async/await并添加挂载状态检查,能有效规避这个问题:
import { Audio } from 'expo-av'; ... useEffect(() => { let soundHandler = null; let isMounted = true; // 标记组件是否仍挂载,防止异步操作后处理无效实例 const loadSound = async () => { try { const { sound } = await Audio.Sound.createAsync( require('../assets/test.mp3'), { shouldPlay: true, isLooping: true } ); if (isMounted) { soundHandler = sound; } } catch (err) { console.error('加载音频失败:', err); } }; loadSound(); return async () => { isMounted = false; if (soundHandler) { try { // 先暂停音频,确保实例处于稳定状态再卸载 await soundHandler.pauseAsync(); await soundHandler.unloadAsync(); } catch (err) { console.log("卸载警告: " + err); } finally { soundHandler = null; // 清空引用,避免内存泄漏 } } }; }, []); ...
改动的原因:
isMounted标志能防止组件卸载后,异步加载完成的回调再给soundHandler赋值,避免后续清理时操作无效实例。- 卸载前先暂停音频,确保实例内部状态稳定,减少事件订阅相关的异常。
- 用
async/await让异步流程更清晰,避免回调嵌套导致的状态不一致。
2. 更新Expo-AV到最新稳定版
这个错误在旧版本的Expo-AV中是已知问题,官方后续版本修复了事件订阅清理的逻辑。你可以运行以下命令更新到兼容版本:
expo install expo-av
3. 避免重复调用卸载操作
如果组件有多次挂载/卸载的场景,要确保不会对同一个sound实例重复调用unloadAsync——第一次卸载后实例已经失效,再次调用就会触发这个错误。上面代码中finally块清空soundHandler的操作就能避免这个问题。
内容的提问来源于stack exchange,提问作者Kemal Kaplan
相关产品推荐
相关产品推荐

