首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >反应:如何防止setInterval在点击按钮启动后被延迟?

反应:如何防止setInterval在点击按钮启动后被延迟?
EN

Stack Overflow用户
提问于 2020-09-25 18:33:39
回答 1查看 252关注 0票数 0

在这个响应庞多罗时钟中,有一个函数countDown启动setInterval,但是当单击按钮id="start_stop"启动countDown时,启动前会有一些延迟。任何帮助都将不胜感激。CodePen.io:https://codesandbox.io/s/tender-wozniak-kfuss

index.js

代码语言:javascript
复制
import React from 'react';
import ReactDOM from 'react-dom';
import './style.css';

/*
* A simple React component
*/
const initState = {
  breakLength: 5,
  sessionLength: 25,
  init: 'session',
  stateIndex: 0,
  timeLeft: undefined,
  timeLeftSeconds: undefined,
  started: false,
  intervalFunc: undefined
}

const states = [ { name: 'session', duration: 1500 }, { name: 'break', duration: 300 } ]

const secondsToMins = (time) => {
  let converted = ('0' + Math.floor(time / 60)).slice(-2) + ':' + ('0' + Math.floor(time % 60)).slice(-2);
  return converted;
}

class Clock extends React.Component {

  constructor(props) {
    super(props);
    this.state = initState;
    this.breakDecrement = this.breakDecrement.bind(this);
    this.breakIncrement = this.breakIncrement.bind(this);
    this.sessionDecrement = this.sessionDecrement.bind(this);
    this.sessionIncrement = this.sessionIncrement.bind(this);
    this.startStop = this.startStop.bind(this);
    this.reset = this.reset.bind(this);
  }

  componentDidMount() {
    let sessionSeconds = this.state.sessionLength * 60;
    this.setState({ timeLeftSeconds: sessionSeconds });
    this.setState({ timeLeft: secondsToMins(sessionSeconds) });
  }

  breakDecrement() {
    // decrements the breakLength and the breakSeconds
    // breakLength is only a number ie. 5 (does not show seconds)
    // breakSeconds is that nunber converted into seconds
    let breakLength = this.state.breakLength - 1;
    if (breakLength > 0 && breakLength < 61){
      this.setState({ breakLength: breakLength });
      let breakSeconds = breakLength * 60;
      states[1]['duration'] = breakSeconds;
    }
  }

  breakIncrement() {
    // same as decrement except does increment
    let breakLength = this.state.breakLength + 1;
    if (breakLength > 0 && breakLength < 61){
      this.setState({ breakLength: breakLength });
      let breakSeconds = breakLength * 60;
      states[1]['duration'] = breakSeconds;
    }
  }

  sessionDecrement() {
    // decrements the sessionLength and the sessionSeconds
    // sessionLength is only a number ie. 25 (does not show seconds)
    // sessionSeconds is that nunber converted into seconds
    let sessionLength = this.state.sessionLength - 1;
    if (sessionLength > 0 && sessionLength < 61){
      states[0]['duration'] = sessionLength*60;
      this.setState(prevState => ({
        sessionLength: prevState.sessionLength-1,
        timeLeftSeconds: (prevState.sessionLength-1)*60,
        timeLeft:  secondsToMins((prevState.sessionLength-1)*60)})
      );
    }
  }

  sessionIncrement() {
    // same as decrement except does increment
    let sessionLength = this.state.sessionLength + 1;
    if (sessionLength > 0 && sessionLength < 61){
      states[0]['duration'] = sessionLength*60;
      this.setState(prevState => ({
        sessionLength: prevState.sessionLength+1,
        timeLeftSeconds: (prevState.sessionLength+1)*60,
        timeLeft:  secondsToMins((prevState.sessionLength+1)*60)})
      );
    }
  }

  startStop(id) {
    // starts the countDown, which runs continuously until the start/stop button
    // is pressed again, which pauses the countdown.
    // the id parameter is used by countDown to play the audio beep
    if(!this.state.started){
      this.countDown(id);
      this.setState({ started: true});
    }
    // pauses the countDown
    if(this.state.started){
      let intervalFunc = this.state.intervalFunc;
      clearInterval(intervalFunc);
      this.setState({ started: false});
    }
  }

  reset() {
    let intervalFunc = this.state.intervalFunc;
    clearInterval(intervalFunc);
    // reset state to default values
    this.setState({ breakLength: 5 });
    this.setState({ sessionLength: 25 });
    this.setState({ init: 'session' });
    this.setState({ timeLeftSeconds: 1500})
    this.setState({ timeLeft: '25:00' });
    this.setState({ stateIndex: 0 });
    this.setState({ started: false });
    this.setState({ intervalFunc: undefined });
  }

  countDown(id){
    // set the function to a variable and set state to it, so the function
    // can be paused with clearInterval()
    var intervalFunc = setInterval(() => down(this.state.timeLeftSeconds--), 1000);
    this.setState({intervalFunc: intervalFunc});

    const down = (time) =>
    {

      if(time > 0){
        // converts seconds to MM:SS at every t-minus
        this.setState({ timeLeft: secondsToMins(time)});
        console.log(time);
        console.log(this.state.timeLeft);
      }

      if (time <= 0) {

        let sound = document.getElementById(id).childNodes[0];
        sound.play();

        let stateIndex = (this.state.stateIndex + 1) % states.length;
        this.setState({ stateIndex: stateIndex});
        this.setState({ timeLeftSeconds: states[stateIndex].duration});
        this.setState({ init: states[stateIndex].name});
        this.setState({ timeLeft: secondsToMins(time)});

        console.log(time);
        console.log(this.state.timeLeft);
        console.log(this.state.init);
      }
    }
  }

  render() {
    return (
      <div id="clock">
      <h1 id="title">25-5 Clock</h1>

      <div>
      <p id="break-label">Break Length</p>
      <p id="break-length">{this.state.breakLength}</p>
      <button id="break-decrement" onClick={e => this.breakDecrement()}> Decrease </button>
      <button id="break-increment" onClick={e => this.breakIncrement()}> Increase </button>
      </div>

      <div>
      <p id="session-label">Session Length</p>
      <p id="session-length">{this.state.sessionLength}</p>
      <button id="session-decrement" onClick={e => this.sessionDecrement()}> Decrease </button>
      <button id="session-increment" onClick={e => this.sessionIncrement()}> Increase </button>
      </div>

      <hr/>

      <div>
      <p id="timer-label">{this.state.init}</p>
      <p id="time-left">{this.state.timeLeft}</p>
      <button id="start_stop" onClick={e => this.startStop(e.target.id)}><audio id="beep" src='./beep.mp3'></audio> start/stop </button>
      <button id="reset" onClick={e => this.reset()}> reset </button>
      </div>

      </div>
    );
  }
};

/*
* Render the above component into the div#app
*/
ReactDOM.render(<Clock />, document.getElementById("app"));

index.html

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
  <meta charset="utf-8">
  <title>25-5 Clock</title>
  <style>
  </style>
</head>
<body>
  <main>
    <div id="app"></app>
    </main>
 </script>
  </body>
  </html>
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-09-25 19:01:51

你有两个问题:

  • Set interval将在1s之后调用。(延迟1秒)
  • 您有方法调用方法,例如:down(this.state.timeLeftSeconds--)将随着当前时间第一次下降,这里没有更改时间,然后this.state.timeLeftSeconds会减少。(延迟1秒)

=>您的代码将延迟2秒.

我的建议是“您应该立即调用函数并修改timeLeftSeconds下的方式”

代码语言:javascript
复制
descreaseCurrentSecond = () => --this.state.timeLeftSeconds;

countDown(id) {
    // set the function to a variable and set state to it, so the function
    // can be paused with clearInterval()
    var intervalFunc = setInterval(
        () => down(this.descreaseCurrentSecond()),
        1000
    );
    this.setState({ intervalFunc: intervalFunc });

    const down = (time) => {
        if (time > 0) {
            // converts seconds to MM:SS at every t-minus
            this.setState({ timeLeft: secondsToMins(time) });
            console.log(time);
            console.log(this.state.timeLeft);
        }

        if (time <= 0) {
            let sound = document.getElementById(id).childNodes[0];
            sound.play();

            let stateIndex = (this.state.stateIndex + 1) % states.length;
            this.setState({ stateIndex: stateIndex });
            this.setState({ timeLeftSeconds: states[stateIndex].duration });
            this.setState({ init: states[stateIndex].name });
            this.setState({ timeLeft: secondsToMins(time) });

            console.log(time);
            console.log(this.state.timeLeft);
            console.log(this.state.init);
        }
    };
    
    down(this.descreaseCurrentSecond());
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64069633

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档