gpt4 book ai didi

javascript - FCC 番茄时钟未通过内置测试

转载 作者:行者123 更新时间:2023-12-04 15:41:00 25 4
gpt4 key购买 nike

我正在做 FCC 练习 Pomodoro Clock 这样的作品。我认为问题是当倒计时到了最后一分钟时,pause 将不起作用。顺便说一句,如果不是最后一分钟,暂停 会起作用。我怀疑这个问题导致其他测试失败。还测试说 reset 功能不起作用,但它有效。

编辑:更深入地解释我的问题:方法 paused() 用于将状态 pausedfalse 更改为 true ,反之亦然。该方法在 timer() 方法内部调用,该方法的工作也是启动 setIntervalsetInterval 设置在变量this.clearTimer 中。如果它是 paused true 则启动 clearInterval() 并停止计时器。

当带有 start_stop id 的元素被点击时,paused 发生变化,评估发生,正如我之前所说的那样; false => setInterval 去; true => setInterval 停止。

未暂停时,根据状态中记录的值设置间隔。问题是,当您暂停低于一分钟(59、58 等秒)的计时器时,尽管暂停的状态从真变为假,它也不会恢复倒计时?!如果倒计时超过 1 分钟,则开始/暂停按规定工作。

您可以在以下位置查看代码:my pen

这是主要组件的代码(来自本地源):

    import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.css';
import './style.scss';
import Item from "./item.js";
import Arrow from "./arrow.js";
import Fa from "./fa.js";

class Pomodoro extends React.Component {

constructor(props) {
super(props);
this.state = {
breakLength: 5,
multiplier: 25,
base: 1000,
time: 0,
minutes: 25,
seconds: 60,
paused: false,
session: false,
break: true,
disabled: false,
};
this.increment = this.increment.bind(this);
this.decrement = this.decrement.bind(this);
this.timer = this.timer.bind(this);
this.reset = this.reset.bind(this);
this.paused = this.paused.bind(this);
this.myRef = React.createRef();
this.clearTimer = null;
}

componentDidMount(){

this.setState({
time: ""+(this.state.multiplier*this.state.base*60),
minutes: this.state.multiplier,
seconds: this.state.seconds === 60 ? "00" : this.state.seconds ,
});

}

paused(){

this.setState({
paused: !this.state.paused
});

}

timer(){

this.paused();

if(this.state.paused === false){

if((this.state.minutes!==0 && this.state.seconds!==0) || (this.state.seconds!==0)){

this.clearTimer = setInterval(() => {

if(this.state.session===false){
console.log("Sada ide session.");

this.setState({
time: ""+(this.state.time-this.state.base),
minutes: this.state.minutes > 0 ? Math.floor(((this.state.time-this.state.base)/(this.state.base))/60) : this.state.minutes,
seconds: this.state.seconds > 0 ? this.state.seconds-1 : 59,
session: (this.state.minutes===0 && this.state.seconds===1) ? true : false,
break: (this.state.minutes===0 && this.state.seconds===1) ? false : true,
});

}

if(this.state.break===false && this.state.session===true && this.state.time==="0"){
console.log("Kraj session-a. Sada ide resetovanje, pa break.");
this.setState({
time: ""+(this.state.breakLength*this.state.base*60),
minutes: this.state.breakLength,
seconds: 60,
});

}

if(this.state.break===false){
console.log("Sada ide break.");
this.setState({
time: ""+(this.state.time-this.state.base),
minutes: this.state.minutes > 0 ? Math.floor(((this.state.time-this.state.base)/(this.state.base))/60) : this.state.minutes,
seconds: this.state.seconds > 0 ? this.state.seconds-1 : 59,
session: (this.state.minutes===0 && this.state.seconds===1) ? false : true,
break: (this.state.minutes===0 && this.state.seconds===1) ? true : false,
});

}

if(this.state.break===true && this.state.session===false && this.state.time==="0"){
console.log("Kraj break-a. Sada ide resetovanje, pa session.");
this.setState({
time: ""+(this.state.multiplier*this.state.base*60),
minutes: this.state.multiplier,
seconds: this.state.seconds === 60 ? "00" : this.state.seconds,
});

}

}, this.state.base);

}

}
else{

clearInterval(this.clearTimer);

}

}

reset(){

this.myRef.current.pause();
this.myRef.current.currentTime = 0;
clearInterval(this.clearTimer);
this.clearTimer = null;
this.setState({
breakLength: 5,
multiplier: 25,
base: 1000,
time: ""+(25*1000*60),
minutes: 25,
seconds: 60,
paused: false,
session: false,
break: true,
disabled: false,
});

}

increment(e){

console.log(e.target.id);
let myId = e.target.id;

if(myId==="break-increment"){

this.setState({
breakLength: this.state.breakLength <60 ? this.state.breakLength+1 : this.state.breakLength,
});

}
else if(myId==="session-increment"){

this.setState({
multiplier: this.state.multiplier < 60 ? this.state.multiplier+1 : this.state.multiplier,
time: this.state.time !== "60" ? ""+((this.state.multiplier+1)*this.state.base*60) : this.state.time,
minutes: this.state.minutes < 60 ? this.state.multiplier+1 : this.state.minutes,
});

}

}

decrement(e){

console.log(e.target.id);
let myId = e.target.id;

if(myId==="break-decrement" && this.state.breakLength > 1){

this.setState({
breakLength: this.state.breakLength > 1 ? this.state.breakLength-1 : this.state.breakLength,
});

}
else if(myId==="session-decrement" && this.state.multiplier > 1 && this.state.time > 1 && this.state.minutes > 1){

this.setState({
multiplier: this.state.multiplier > 1 ? this.state.multiplier-1 : this.state.multiplier,
time: this.state.time > 1 ? (""+((this.state.multiplier-1)*this.state.base*60)) : this.state.time,
minutes: this.state.minutes > 1 ? this.state.multiplier-1: this.state.minutes,
});

}

}

render(){
//console.log(this.state);

const minutes = (""+this.state.minutes).length===1 ? "0"+this.state.minutes : this.state.minutes;
const seconds = this.state.seconds===60 ? "00" : ((""+this.state.seconds).length===1 ? "0"+this.state.seconds : this.state.seconds);
const time = minutes+":"+seconds;

if(time==="00:00"){
console.log("1: "+time);
console.log("2: "+this.state.minutes+":"+this.state.seconds);
this.myRef.current.play();
}

/*if((this.state.minutes+":"+this.state.seconds)===time){
alert("alert2: "+this.state.minutes+":"+this.state.seconds);
}*/

const lastSesMin = (minutes==="00") ? {color: 'red',} : {};

const decrement = this.clearTimer ? ()=>{} : this.decrement;
const increment = this.clearTimer ? ()=>{} : this.increment;

const item2Head = <h3 id="break-label">Break Length</h3>;
const fa1 = <Fa klasa={"fa fa-arrow-down fa-2x"} id={"break-decrement"} onClick={decrement}/>;
const fa2 = <Fa klasa={"fa fa-arrow-up fa-2x"} id={"break-increment"} onClick={increment}/>;
const arr1 = [<Arrow klasa={"arrow"} key={0} arrow={item2Head}/>, <br key={1}/>, <Arrow klasa={"arrow"} key={2} arrow={fa1}/>, <Arrow id={"break-length"} klasa={"nums"} key={3} arrow={this.state.breakLength}/> , <Arrow key={4} klasa={"arrow"} arrow={fa2}/>];

const item3Head = <h3 id="session-label">Session Length</h3>;
const fa3 = <Fa klasa={"fa fa-arrow-down fa-2x"} id={"session-decrement"} onClick={decrement}/>;
const fa4 = <Fa klasa={"fa fa-arrow-up fa-2x"} id={"session-increment"} onClick={increment}/>;
const arr2 = [<Arrow klasa={"arrow"} key={0} arrow={item3Head}/>, <br key={1}/>, <Arrow klasa={"arrow"} key={2} arrow={fa3}/>, <Arrow klasa={"nums"} id={"session-length"} key={3} arrow={this.state.multiplier}/> , <Arrow key={4} klasa={"arrow"} arrow={fa4}/>];

const countdownLabel = (this.state.session===false && this.state.break===true) ? "Session" : "Break";
const item4Head = <h3 key={0} id={"timer-label"} style={lastSesMin}>{countdownLabel}</h3>;
const nums2 = <div key={1} className="nums" style={lastSesMin} id={"time-left"}>{time}</div>;
const arr3 = [item4Head, nums2];

const fa5 = <Fa key={0} klasa={"fa fa-play arrow controls"} title={"start-pause"}/>;
const fa6 = <Fa key={1} klasa={"fa fa-pause arrow controls"} title={"start-pause"}/>;
const fa7 = <Fa key={2} klasa={"fa fa-refresh arrow controls"} id="reset" title={"reset"} onClick={this.reset}/>;
const startPause = <div id="start_stop" key={4} onClick={this.timer}>{fa5}{fa6}</div>;
const arr4 = [startPause, fa7];

return(
<div className="grid-container cent">

<Item klasa={"item1"} arrowsAndNums={"Pomodoro Clock"}/>

<Item klasa={"item2"} arrowsAndNums={arr1}/>

<Item klasa={"item3"} arrowsAndNums={arr2}/>

<Item klasa={"item4"} arrowsAndNums={arr3}/>

<Item klasa={"item4"} arrowsAndNums={arr4}/>
<audio ref={this.myRef} id="beep" src="http://soundbible.com/grab.php?id=2158&type=wav"></audio>
</div>
);

}

}

ReactDOM.render(<Pomodoro/>, document.getElementById('root'));

编辑2:我解决了暂停问题。我刚刚将 if(this.state.minutes!==0 && this.state.seconds!==0){ 行更改为 if((this.state.minutes!== 0 && this.state.seconds!==0) || (this.state.seconds!==0)){.

这里有一些图像显示了测试错误,即使应该没有错误。PS:对于练习的错误测试,它使用了 fcc 的错误测试脚本,这就是产生这些假定错误的原因。

错误的图片 1: Image1 of the errors

错误的图片 2: enter image description here

编辑 3:以及可能来自测试套件的错误图像: enter image description here

编辑4:正如我最近发现的那样,即使是 FCC 的番茄钟有时也会失败。有时在不同的浏览器中,有时在星期天,有时等等......长话短说,我设计了新代码,解决了我之前所做编辑中的问题。尽管如此,它仍然存在与上述 fcc 的番茄钟相同的问题。我在某处读到一些关于计时事件的内容,其实现和执​​行取决于浏览器,在这种情况下,测试套件本身使用,我的番茄钟也是如此。所以应该有各种各样的“冲突”......解决这些不一致和冲突,以便在每个浏览器中,在每一个诉讼/测试中,看起来都无法克服,我想会......我想问的是,可以吗如果我提交我的番茄钟,关于所说的一切?我的改进pomodoro添加了解释代码功能的注释,请随意浏览。我的测试失败的图像:failed test在左上角,您可以看到 28/29 通过的测试。注意:您可以在 codepen 中看到更新后的代码以及注释。

最佳答案

只是阅读了一些代码(没有测试你的沙箱),但我发现了一个问题,由于可能的竞争条件,可能会导致一些模糊的错误:

paused(){

this.setState({
paused: !this.state.paused
});

}

timer(){

this.paused();

if(this.state.paused === false){

// ...

timer() 正在调用 paused,其中状态已更新。然后 timer() 检查新状态。

问题:

  1. setState may be batched ,因此对 paused 的连续调用可能基于某个值。

解决方案:使用函数作为状态更新器:

setState(prevState => ({
paused: !prevState.paused
}));
  1. setState may be asynchronous (相同的链接),因此 paused 状态在 timer() 中读取时可能不会反射(reflect)该更改!

解决方案:使用回调作为 setState() 的第二个参数:

setState(prevState => ({
paused: !prevState.paused
}), () => {
// You can read updated this.state.paused here....
});

所以整个代码片段可以这样实现:

 paused(callback){
setState(prevState => ({
paused: !prevState.paused
}), callback);
}

timer(){

this.paused(() => {

// if(this.state.paused === false){
// ...
});

但是如果你有很多这样的地方,你很快就会陷入某种回调 hell 。并且在这些状态变化的同时管理停止/启动计时器本身可能会变得非常棘手。你至少可以简化你的计时器,但让它始终运行(从 componentDidMount() 开始,在 componentWillUnmount() 停止)并决定每个滴答做什么(例如做“暂停”或让“暂停”指示灯闪烁时什么都没有...)

旁注:像 base 这样的变量不需要处于状态,因为它们只是不需要触发组件重新渲染的内部变量。

关于javascript - FCC 番茄时钟未通过内置测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57798187/

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