如何避免慢 setInterval?
Posted
技术标签:
【中文标题】如何避免慢 setInterval?【英文标题】:How to avoid Slow setInterval? 【发布时间】:2020-01-06 19:39:01 【问题描述】:我有一个从数据库中获取的语音 URL,并想使用 react-native-sound 播放它,
所以我制作了一个可重用的组件,它“现在没有动画”呈现播放图标和持续时间
所以在声音播放之后,我先更改播放图标,然后运行setInterval
以每秒增加计数+1
但一开始更改图标和实际持续时间太慢了,以秒为单位:11但计时器在9停止
那么我怎样才能让它更快...
代码
this.state =
playingNow: false,
spinValue: new Animated.Value(0),
timer: 0,
;
// get URL sound from DB then play it :)
play = async () =>
const VoiceURL = this.props;
console.log('Play Func Object:', VoiceURL);
const sound = new Sound(VoiceURL, '', error =>
if (error)
console.log('failed to load the sound', error);
return;
else
// Animated.timing(this.state.spinValue,
// toValue: 1,
// duration: sound. _duration * 1100 || 1000,
// easing: Easing.linear,
// useNativeDriver: true,
// ).start(() =>
// this.state.spinValue.setValue(0);
// );
this.interval = setInterval(
() =>
this.setState(
playingNow: true,
timer: this.state.timer + 1,
),
1000,
);
sound.play(success =>
if (success)
// That's mean sound is finish
console.log('success?', success);
this.setState(
playingNow: false, timer: 0,
() => sound.stop(),
clearInterval(this.interval),
);
console.log('successfully finished playing');
else
console.log('playback failed due to audio decoding errors');
);
console.log(
'duration in seconds: ' +
sound.getDuration() +
'number of channels: ' +
sound.getNumberOfChannels(),
);
sound.getCurrentTime(seconds => console.log('at: ' + seconds));
sound.setNumberOfLoops(0);
);
console.log('in_play??', sound);
return sound;
;
这就是渲染一个 UI
_renderPlayButton = onPress =>
const timer = this.state;
let icon = this.state.playingNow ? 'pause' : 'play-arrow';
// const spin = this.state.spinValue.interpolate(
// inputRange: [0, 1],
// outputRange: [0, -120],
// );
return (
<View
style=
opacity: this.props.opacity,
alignItems: 'center',
flexDirection: 'row',
>
<TouchableOpacity
style=backgroundColor: '#1E558E', borderRadius: 100
onPress=onPress>
<Icon name=icon color="#fff" size=25 style=padding: 2 />
</TouchableOpacity>
<View
style=flexDirection: 'row', marginLeft: 5, alignItems: 'center'>
/* <Animated.View
style=
backgroundColor: '#f00',
borderRadius: 10,
width: 15,
height: 15,
zIndex: 10,
transform: [translateX: spin],
/> */
<View
style=
width: 120,
backgroundColor: '#a7a7a7',
height: 2,
/>
<Text style=color: '#777', marginBottom: 5, marginLeft: 10>
00:
('0' + (timer || 0)).slice(-2)
console.log('timer-state:', timer)
</Text>
</View>
</View>
);
;
JSX
<View>
this._renderPlayButton(() =>
this.play();
)
</View>
【问题讨论】:
不知道这是否是问题的原因,但您不应在传递给setState
的对象中直接使用this.state
。请改用function form。
@RobinZigmond U 的意思是setState
计时器?
是的。将其更改为this.setState(oldState => (playingNow: true, timer: oldState.timer + 1))
。我不能肯定地说这会解决问题(如果我确定我会给出答案),但在我看来这当然是可能的。我链接到的文章应该解释为什么这是必要的。
@RobinZigmond 遗憾地没有解决问题:\
@RobinZigmond 当我使用这种方式并在_renderPlayButton()
中记录timer
时,它记录了 125 次,虽然声音只有 3 秒:O
【参考方案1】:
在处理实时数据时,永远不要自己计算,始终使用可用的真实数据。
使用Sound
,它看起来像getCurrentTime
。起初,它会显示为0
秒,这就是您使用间隔开头的原因。
// Set it playing as soon as possible.
this.setState( playingNow: true );
this.interval = setInterval(
() =>
sound.getCurrentTime(seconds =>
this.setState( timer: Math.floor(seconds) );
),
500 // reduce the delay so it don't skip a second.
);
请注意,我没有测试此答案中的代码。此外,对componentWillUnmount
进行正确清理也很重要,例如在声音对象上调用.release()
。
【讨论】:
release()
是做什么的,为什么要在componentWillUnmount
上调用它
@DevAS 根据文档,它会释放音频的内存。不过,我从来没有做过 React Native 开发,也没有使用过这个 API,所以我不能确定最好在哪里调用它。
@EmileBergeron 感谢您的回答,但我在十进制中得到了秒,像这样 2.072 它不能很好地工作,何时使用 Math.floor(second) 它跳过了一些数字
@OliverD 我更新了答案,因此不太可能跳过第二次更新。
@EmileBergeron 嗨,希望你一切都好。我有一个简单的问题,是否可以使用 setInterval 并继续每 5 秒调用一次我的 API 获取请求,否则会导致性能问题吗?以上是关于如何避免慢 setInterval?的主要内容,如果未能解决你的问题,请参考以下文章
React.js/Redux:Reducers 中的 setInterval 和 clearInterval