使用Expo AV在React Native中播放音频5秒后停止报错,求原因
问题原因及解决方案
报错原因
你在onPress回调里调用await playSound()后,立刻通过setTimeout去执行sound.stopAsync(),但React的setSound是异步状态更新方法——组件的sound状态并不会在playSound执行完毕后立刻更新。当5秒后setTimeout触发时,组件的sound变量还是初始的undefined,自然会抛出“找不到stopAsync方法”的错误。
修复方案
方案一:让playSound返回实例,直接在onPress里使用
不用依赖组件状态,直接获取创建的sound实例进行操作:
const [sound, setSound] = React.useState(); async function playSound() { console.log("Loading Sound"); const { sound } = await Audio.Sound.createAsync( require("./assets/sound.mp3") ); setSound(sound); console.log("Playing Sound"); await sound.playAsync(); return sound; // 返回创建的sound实例 } React.useEffect(() => { return sound ? () => { console.log("Unloading Sound"); sound.unloadAsync(); } : undefined; }, [sound]); // ... <Button title="Play" onPress={async () => { const soundInstance = await playSound(); // 接收返回的实例 setTimeout(async () => { await soundInstance.stopAsync(); // 直接用实例调用停止方法 }, 5000); }} />
方案二:把定时逻辑放到playSound内部
直接在创建sound实例的函数里处理定时停止,避免依赖组件状态:
const [sound, setSound] = React.useState(); async function playSound() { console.log("Loading Sound"); const { sound } = await Audio.Sound.createAsync( require("./assets/sound.mp3") ); setSound(sound); console.log("Playing Sound"); await sound.playAsync(); // 直接在内部设置定时停止 setTimeout(async () => { await sound.stopAsync(); }, 5000); } React.useEffect(() => { return sound ? () => { console.log("Unloading Sound"); sound.unloadAsync(); } : undefined; }, [sound]); // ... <Button title="Play" onPress={playSound} />
内容的提问来源于stack exchange,提问作者Benjamin Jones
相关产品推荐
相关产品推荐

