简体   繁体   English

如何制作一个计时器,在 React Native 中以精确的时间间隔滴答和显示时间?

[英]How to make a timer that ticks and display time at an exactly interval in React Native?

Edit:编辑:

In RN, setInterval isn't going to be exactly at the interval you want.在 RN 中, setInterval不会正好是您想要的时间间隔。 Sometimes it will take longer有时需要更长的时间

How can I implement a timer that ticks and display the time exactly at the interval you provide (eg 100 milliseconds)我如何实现一个计时器,它可以准确地按照您提供的时间间隔(例如 100 毫秒)滴答和显示时间

The timer should count time the same way as the native timers that already comes with the mobile.计时器应该以与手机自带的本机计时器相同的方式计算时间。

*Bellow this point is just what I tried to do, but it can be ignored or used to come with a solution *下面这一点正是我尝试做的,但可以忽略或用于解决方案


Background:背景:

I'm making a timer.我在做一个计时器。 To display it on the screen I made an object like the following为了在屏幕上显示它,我制作了一个如下所示的对象
eg例如

let time = {
    milliseconds: 1,
    seconds: 2,
    minutes: 3
}

and I have a setInterval that subtracts x milliseconds from this object.我有一个setInterval从这个对象中减去x毫秒。

What I'm trying to do:我想做什么:

I need the fastest and optimal way to subtract milliseconds from this object.我需要最快和最佳的方法来从这个对象中减去毫秒数。 Following the normal time rule ( 1000 milliseconds is 1 seconds, 60 seconds is 1 minute ) and it also needs to stop at 0 if you get negative time.遵循正常的时间规则(1000 毫秒为 1 秒,60 秒为 1 分钟),如果您得到负时间,它也需要在0处停止。
It should feel like a native timer.它应该感觉像一个本地计时器。

What I have tried:我试过的:

This is the function that I use to subtract milliseconds from my timer object:这是我用来从计时器对象中减去毫秒的函数:

export function minusTime(time, millis) {

    let milliseconds = parseInt(millis % 1000)
    let seconds = Math.floor((millis / 1000) % 60)
    let minutes = Math.floor((millis / (1000 * 60)))

    if (time.minutes - minutes < 0) {
        return -1
    }
    time.minutes -= minutes
    if (time.seconds - seconds < 0) {
        if (time.minutes - 1 < 0) {
            return -1
        } else {
            time.minutes -= 1
            time.seconds += 60
        }
    }
    time.seconds -= seconds
    if (time.milliseconds - milliseconds < 0) {
        if (time.seconds - 1 < 0) {
            if (time.minutes - 1 < 0) {
                return -1
            } else {
                time.minutes -= 1
                time.seconds += 59
                time.milliseconds += 1000
            }
        } else {
            time.seconds -= 1
            time.milliseconds += 1000
        }
    }
    time.milliseconds -= milliseconds
    return time

}

The logic is correct ( but also looks a little ugly, if there is a better way of doing this, I appreciate it ).逻辑是正确的(但也看起来有点丑,如果有更好的方法,我很感激)。

The way I use the interval is this useInterval hook我使用间隔的方式是这个useInterval 钩子

function useInterval(callback, delay) {
    const savedCallback = useRef()

    // Remember the latest callback.
    useEffect(() => {
        savedCallback.current = callback
    }, [callback])

    // Set up the interval.
    useEffect(() => {
        function tick() {
            savedCallback.current()
        }
        if (delay !== null) {
            let id = setInterval(tick, delay)
            return () => clearInterval(id)
        }
    }, [delay])
}

And in my component I call it like在我的组件中,我称它为

useInterval(() => {
        ...
        let blockTime = minusTime(currentBlock.blockTime, interval)
        ...
}, isRunning ? interval : null)

And I just display it like我只是像这样展示它

<Text>                            
    {`${minutes}:${seconds},${milliseconds}`}
</Text>

The Problem:问题:

When I run this, 1 seconds in my timer isn't 1 real life seconds.当我运行它时,计时器中的 1 秒不是现实生活中的 1 秒。

How can I make it to be 1 real life second?我怎样才能让它成为现实生活中的一秒? Is my functions taking too long to run and that is why it's slow?我的函数运行时间是否太长,这就是它运行缓慢的原因? Or I need something else?或者我需要别的东西?

How to execute my timer so it's match 1 second in real life?如何执行我的计时器,使其在现实生活中匹配 1 秒?
Is there a better way to deal with my timer object?有没有更好的方法来处理我的计时器对象?

I have found a way to work this out for timers.我找到了一种为计时器解决这个问题的方法。

I implemented Yossi idea and it works!我实施了Yossi的想法并且它有效!

His idea (or what I understand of it) is to calculate the real time that the setInverval took to run and not the interval provided to the setInterval .他的想法(或者我的理解)是计算setInverval运行的实际时间,而不是提供给setInterval的时间间隔。 You need to keep track of the time between intervals.您需要跟踪间隔之间的时间。

I also made an article about it how to do this in javascript.我还写了一篇关于如何在 javascript 中执行此操作的文章。

Here is the implementation in ReactJs, which is the same for React Native, you only need to change what it renders.这里是ReactJs中的实现,React Native也是一样的,你只需要改变它渲染的内容即可。

I also test this in my React Native timer to check if this strategy works, and yes, it works.我还在我的 React Native 计时器中对此进行了测试,以检查该策略是否有效,是的,它有效。

Thank You Yossi!谢谢约西!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM