Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/react-native/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript setInterval和setTimeout延迟问题_Javascript_React Native_Settimeout_Setinterval - Fatal编程技术网

Javascript setInterval和setTimeout延迟问题

Javascript setInterval和setTimeout延迟问题,javascript,react-native,settimeout,setinterval,Javascript,React Native,Settimeout,Setinterval,我一直在尝试通过react native中的递归setTimeout来管理计时器 但我面临的问题是,在某些设备中,计时器在运行过程中花费的时间更多(比如100-150秒计时器中的1-4秒) 我已经删除了setInterval,因为它比递归setTimeout更糟糕。有什么办法可以让这个计时器完美吗 编辑:主要问题是我在2个或更多设备中运行了应用程序(在发布模式下)。计时器可以完美启动,但设备的延迟似乎很小,并且随着时间的推移而增加 应用程序中的api调用是并行完成的 代码: AnotherTim

我一直在尝试通过react native中的递归setTimeout来管理计时器

但我面临的问题是,在某些设备中,计时器在运行过程中花费的时间更多(比如100-150秒计时器中的1-4秒)

我已经删除了setInterval,因为它比递归setTimeout更糟糕。有什么办法可以让这个计时器完美吗

编辑:主要问题是我在2个或更多设备中运行了应用程序(在发布模式下)。计时器可以完美启动,但设备的延迟似乎很小,并且随着时间的推移而增加

应用程序中的api调用是并行完成的

代码:

AnotherTimerHandler=()=>{
this.time=setTimeout(()=>{
if(this.state.gameState==timesup){
console.log(timesup)
this.setState({timer:this.state.timer-1});
if(this.state.timer this.props.navigation.navigate('Winner',{gameId:gameIdToLoad,prizeAmount:this.props.navigation.state.params.QuizData.prizeAmount}))
.catch(err=>alert(err))
}else{this.props.navigation.navigate('Winner',{gameId:gameIdToLoad,prizeAmount:this.props.navigation.state.params.QuizData.prizeAmount});}
}
}
}
else if(this.state.gameState==播放){
console.log('playing')
if(this.state.timer==questionTimer){
//console.log('playing1',this.state.timer)
//this.setState({answerLoaded:false})
//这是Qandandhandler(问题)
此.refs.circularProgress.performLinearAnimation(0,(提问计时器-1)*1000)
}
this.setState({timer:this.state.timer-1})
//if(this.state.timer==-1){
如果(this.state.timer“永远不能保证计时”,
但150ms间隔上的4秒差异确实可以被视为很大

避免这种情况的一种方法是将计时划分为更小的动态时间间隔,并自行校正其延迟

下面是一个哑实现,它会将下一个滴答声重新安排到下一秒,并在每个滴答声时更正其延迟:

//自校正设置间隔
//用于长时间间隔
//返回一个对象,该对象的“\u id”属性是内部超时id,因此可以通过clearInterval取消它
功能自校正间隔(cb、ms){
var innerTimeout=ms<1000?100:1000,//每隔?s激发一次
begin=performance.now(),//现在几点了?
last=begin+ms,//这一切应该在什么时候结束?
next=Math.min(innerTimeout,毫秒),
prev=开始,
结果={
_id:setTimeout(内部,下一个)
},
passed=true;//用于避免try-catch回调的标志
返回结果;
函数内部(){
如果(!通过)返回;
passed=false;//设置回调陷阱
var shouldCall=false;
var now=performance.now(),
延迟=(现在-上一个)-内部超时;
prev+=innerTimeout;//固定增量
如果(上次-现在<6){
shouldCall=true;
begin=last;//开始新的间隔
最后+=ms;
}
next=Math.min(innerTimeout-delay,last-now);
结果。_id=setTimeout(内部,下一个);
//在最后调用它,这样我们就可以在回调中取消
如果(应该打电话){
cb();
}
passed=true;//没有抛出,我们可以继续
}
}
//仅片段测试
功能测试(ms){
函数setTimeoutLoop(cb,ms){
函数循环(){
cb();
设置超时(循环,毫秒);
}
设置超时(循环,毫秒);
}
var now=performance.now(),
内置的上一个=现在,
超时\u prev=现在,
sCI_prev=现在,
内置元素=document.querySelector(“#test_u”+ms+”.delay.build_-in'),
timeout_elem=document.querySelector('#test_'+ms+'.delay.timeout'),
sCI_elem=document.querySelector('#test_'+ms+'.delay.sCI');
设置间隔(()=>{
var now=performance.now(),
延迟=(现在-内置-上一版本)-毫秒;
内置的上一个+=毫秒;
内置元素textContent=Math.round(延迟);
},ms);
setTimeoutLoop(()=>{
var now=performance.now(),
延迟=(现在-超时\u prev)-ms;
超时时间_prev+=ms;
timeout_elem.textContent=Math.round(延迟);
},ms);
自校正间隔(()=>{
var now=performance.now(),
延迟=(现在-sCI_prev)-ms;
sCI_prev+=ms;
sCI_elem.textContent=数学轮(延迟);
},ms);
}
测试(1000);
测试(5000);
测试(60000);
测试(150000);
[id^='test']{
边框:1px实心;
填充:0 12px
}

1000ms间隔的内置设置间隔延迟:0ms

内置设置1000毫秒间隔的超时循环延迟:0毫秒

1000ms间隔的自校正间隔延迟:0ms

5000ms间隔的内置设置间隔延迟:0ms

内置设置5000ms间隔的超时循环延迟:0ms

5000ms间隔的自校正间隔延迟:0ms

内置设置间隔延迟1分钟:0毫秒

内置设置超时循环延迟1分钟间隔:0毫秒

1分钟间隔的自校正间隔延迟:0毫秒

内置设置150秒间隔的间隔延迟:0毫秒

内置setTimeout循环延迟150s间隔:0ms

150秒间隔的自校正间隔延迟:0毫秒

“时间永远无法保证”,
但150ms间隔上的4秒差异确实可以被视为很大

避免这种情况的一种方法是将计时划分为更小的动态时间间隔,并自行校正其延迟

下面是一个哑实现,它会将下一个滴答声重新安排到下一秒,并在每个滴答声时更正其延迟:

//自校正设置间隔
//用于长时间间隔
//返回一个对象,该对象的“\u id”属性是内部超时id,因此可以通过clearInterval取消它
函数自校正
AnotherTimerHandler = () => {
    this.time = setTimeout(() => {
        if (this.state.gameState == timesup) {
            console.log(timesup)
            this.setState({ timer: this.state.timer - 1 });
            if (this.state.timer <= 0) {
                if (this.state.questionIndex < numberOfQuestions - 1) {
                    this.setState({ gameState: splash, timer: splashTime, QAndA: {}, correctAnswer: '', questionIndex: this.state.questionIndex + 1, answered: false })
                } else {
                    // console.log('123')
                    clearInterval(this.time)
                    console.log(this.state.playerMode)

                    if (this.state.playerMode) {
                        const { username, firstName, lastName } = this.props.navigation.state.params.userData;
                        firebase.database().ref(`tblGame/${gameIdToLoad}/gameWinners`).push({ Email: firebase.auth().currentUser.email, Name: firstName + ' ' + lastName })
                            .then(() => this.props.navigation.navigate('Winner', { gameId: gameIdToLoad, prizeAmount: this.props.navigation.state.params.QuizData.prizeAmount }))
                            .catch(err => alert(err))
                    } else { this.props.navigation.navigate('Winner', { gameId: gameIdToLoad, prizeAmount: this.props.navigation.state.params.QuizData.prizeAmount }); }
                }
            }
        }
        else if (this.state.gameState == playing) {
            console.log('playing')
            if (this.state.timer == questionTimer) {
                // console.log('playing1', this.state.timer)
                // this.setState({ answerLoaded: false })
                // this.QAndAHandler(Question)
                this.refs.circularProgress.performLinearAnimation(0, (questionTimer - 1) * 1000)
            }
            this.setState({ timer: this.state.timer - 1 })
            // if (this.state.timer == -1) {
            if (this.state.timer <= 0) {
                this.setState({ gameState: timesup, timer: answerTimer }); this.QAndAHandler(Ans);
                // console.log('playing2', this.state.timer)
            }
        }
        else if (this.state.gameState == splash) {
            console.log(splash)
            console.log(this.state.timer)
            this.setState({ timer: this.state.timer - 1 })
            if (this.state.timer == splashTime - 1) {
                this.QAndAHandler(Question)
            } else if (this.state.timer <= 0) this.setState({ timer: questionTimer, gameState: playing, answerLoaded: false })
        }
        // Dont call again if scren is being changed 
    return this.state.gameState == timesup && this.state.timer<=0 && !(this.state.questionIndex < numberOfQuestions - 1) ? null : this.AnotherTimerHandler()    
    }, 1000)
}