首页 > 解决方案 > 在 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);
        });
    };

标签: reactjsreact-native

解决方案


@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”上的当前时刻


推荐阅读