gpt4 book ai didi

javascript音频对象addeventlistener不更新状态

转载 作者:行者123 更新时间:2023-11-28 05:24:44 25 4
gpt4 key购买 nike

我有一个像这样的 react 组件:

class MusicProgress extends Component {

constructor(props) {
super(props)
this.state = { progress: 1, percentage: 1 }
}

get_progress() {
if(!this.audio) {
this.audio = new Audio(music_url)
}
var progress = this.state.progress
var self = this
this.audio.addEventListener('loadedmetadata', function() {
var duration = self.audio.duration
if(!(progress >= duration)) {
setTimeout(function(){
progress += 1
var percentage = ((progress / duration) * 100).toFixed()
self.setState({'progress': progress, 'percentage': percentage})
}, 1000)
}
})
}

render() {
return (
<div >
<p>{this.state.percentage}</p>
{this.get_progress()}
</div>
)
}
}

这里,如果 this.audio 不可用,我将音频对象分配给 this,例如 this.audio。然后我正在创建新对象。

我正在使用 this.audio.addEventListener('loadedmetadata', function() { 来获取音频的持续时间,以便我可以计算每次播放后的百分比1 秒。

一开始它工作得很好,我在 1 秒后得到了百分比,但在那之后它没有给出百分比。 percentage 更新为状态后 this.audio 未进入 eventListener

这里出了什么问题?需要建议请LZ

最佳答案

这只是伪代码,可能行不通,但这里有很多不好的做法。

不要在 render 方法中调用调用 setState 的函数。看起来您的逻辑应该为每个新的音频网址发生一次。

为此,您只需要创建音频实例并在 init 时监听事件一次,以及 musicUrl 属性是否发生更改。不是每个渲染..

您也没有清理之前的 setTimeouts、事件监听器或音频实例。

我会更像这样构建它:

class MusicProgress extends Component {

constructor(props) {
super(props)
this.state = {
percentage: 1,
progress: 1,
};
}

// Because you should not setState from the constructor (initAudio does).
componentDidMount() {
initAudio(this.props.musicUrl);
}

componentWillReceiveProps(nextProps) {
if (nextProps.musicUrl !== this.props.musicUrl) {
this.destroyAudioInst();
initAudio(nextProps.musicUrl);
this.setState({
percentage: 1,
progress: 1,
});
}
}

destroyAudioInst() {
// this.state.audioInst.destroy(); // If necessary
this.state.audioInst.removeEventListener('loadedmetadata');
clearTimeout(this.audioTickId);
this.audioTickId = null;
}

initAudio(musicUrl) {
const audioInst = new Audio(musicUrl);
let { progress } = this.state;

audioInst.addEventListener('loadedmetadata', () => {
const duration = audioInst.duration;
if (progress < duration) {
this.audioTickId = setTimeout(() => {
progress += 1;
const percentage = ((progress / duration) * 100).toFixed();
this.setState({
audioInst,
progress: progress,
percentage: percentage,
});
}, 1000);
}
});
}

render() {
if (!this.state.audioInst) {
return <div>Loading...</div>;
}

return (
<div>
<p>{this.state.percentage}</p>
{this.state.progress}
</div>
);
}
}

关于javascript音频对象addeventlistener不更新状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40263399/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com