reactjs - 在 react-native 暂停后重新启动时,计时器会提前几秒钟
问题描述
我有一些逻辑来处理我的 react-native 应用程序中的计时器。现在我正在观察一些奇怪的行为。当我第一次启动计时器时,它会按预期运行。当我单击stop
它时,它会显示最后一个值。然后,当我再次单击开始时,它应该获取最后一个值并继续递增。但是,正在发生的事情是重新启动,值会提前几秒钟,并从那里增加,我不知道为什么。
有四个主要组成部分:_startTimer()
、_stopTimer()
、calculateDuration()
和continueTimer()
。
问题似乎在_continueTimer()
运行时发生,特别_calculateDuration()
是在从该函数中调用时。
constructor(props) {
super(props);
this.timer = null;
this.state = {
duration: props?.duration || '00:00:00',
startTime: props?.started ? moment(props.started).format('YYYY-MM-DD HH:mm:ss') : null,
stopTime: props?.stopped ? moment(props.stopped).format('YYYY-MM-DD HH:mm:ss') : null,
};
}
async _startTimer() {
if (this.timer) clearInterval(this.timer);
let stateUpdate = {
stopTime: null,
};
if (!this.state.startTime) {
const newStartTime = moment(Date.serverTime() || Date.now());
stateUpdate.startTime = newStartTime.format('YYYY-MM-DD HH:mm:ss');
}
this.setState(stateUpdate, () => {
this.timer = setInterval(async () => {
const newDuration = this._calculateDuration();
this.setState({
duration: newDuration,
});
}, 1000);
if (this.props.onChange) this.props.onChange(this.state);
});
};
_stopTimer() {
return new Promise((resolve) => {
if (this.timer) clearInterval(this.timer);
const newStopTime = moment(Date.serverTime());
this.setState({
stopTime: newStopTime.format('YYYY-MM-DD HH:mm:ss'),
}, async () => {
if (this.props.onChange) await this.props.onChange(this.state);
});
});
};
_calculateDuration() {
const startTime = moment(this.state.startTime).valueOf();
const stopTime = this.state.stopTime ? moment(this.state.stopTime).valueOf() : moment().valueOf();
const duration = moment.duration(stopTime - startTime).asMilliseconds();
const durationFormatted = moment.utc(duration).format('HH:mm:ss');
return durationFormatted;
};
async _continueTimer() {
if (this.timer) clearInterval(this.timer);
this.setState({
stopTime: null,
}, () => {
this.timer = setInterval(async () => {
const newDuration = this._calculateDuration();
this.setState({
duration: newDuration,
});
}, 1000);
if (this.props.onChange) this.props.onChange(this.state);
});
};
解决方案
@muirik我刚刚尝试跟踪调用链,我认为正在发生的事情是在停止之后,然后重新启动,_startTimer()
被调用而不是_continueTimer()
. 要么是这样,要么是您没有重置方法state.Starttime
中的值_continueTimer()
。无论哪种方式,原因都是一样的:
下面的例子
如果您使用全新的计时器:
Start button is hit, start time is 12:00:00 (For sake of argument)
等待 1 秒
interval happens, duration is calculated as 12:00:01 - 12:00:00 = 0:0:01
按停止
StopTimer happens,stop time is 12:00:01 , duration is 0:0:01
等待 5 秒
再次按下开始按钮(假设调用开始而不是继续)
start sets state.stopTime to null, then skips the following:
if (!this.state.startTime) {
const newStartTime = moment(Date.serverTime() || Date.now());
stateUpdate.startTime = newStartTime.format('YYYY-MM-DD HH:mm:ss');
}
start time is still 12:00:01
1 秒过去 - 时间是 12:00:07
Time interval gets called, difference is calculated. start time is 12:00:01, current time is 12:00:07 , duration goes from 0:0:01 to 0:0:07
我的建议是查看您调用这些方法的位置,并将开始时间状态设置为“continueTime”上的当前时刻
推荐阅读
- javascript - 带有 HTTP 请求的单元测试返回 Promise {
} - angular - Angular 4 Reactive form reset() 函数在重置时显示错误消息
- awk - 在 awk 中组合和处理 2 个制表符分隔的文件并创建一个新文件
- python - 如何使用 python one-liner 从 bash 中的 json 文件中获取嵌套键的值?
- ios - swift - tableViewCell 内的项目的动态列表
- xamarin - 如何将视图检测为父视图
- kotlin - Protobuf 中的 Kotlin 数据类支持
- c# - 使用 System.IO.Directory.CreateDirectory() 时出现 FileNotFoundException
- c# - Windows 用户密码验证
- sql-server - SQL使用存储过程从excel中插入日期