Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accuracy of setTimeout in React Native

I'm building a metronome in React Native. After playing a click, I set a setTimeout for the next click. The timing however, is awful.

I did the following quick test:

let time = (new Date()).getTime() + 50;

setTimeout(() => {
  console.log(time - (new Date()).getTime());
}, 50)

Ideally, I should get 0 in the console. While running this outside React Native in Chrome Dev Tools, I get -1, sometimes -2 (ms). This is an acceptable result.

Running this inside React Native using the Simulator on macOS I get values between 0 and -100. This clearly is not acceptable.

Does someone know if this is due to the inaccuracy of setTimeout or the inaccuracy of (new Date()).getTime()? Can I fix this?

like image 620
Arthur C Avatar asked Feb 07 '17 21:02

Arthur C


People also ask

Why setTimeout function does not have latest state value?

This boils down to how closures work in JavaScript. The function given to setTimeout will get the flag variable from the initial render, since flag is not mutated.

Is clearTimeout necessary in React?

You only need to clear the timeout if you want the timer not to fire if it hasn't already fired. If it's already fired, or you don't care if it fires in the future, you don't need to cancel it.

Does setTimeout React work?

Using the setTimeout function works the same in React as it does in plain JavaScript.

What is requestAnimationFrame react native?

requestAnimationFrame() method tells the browser that you wish to perform an animation and requests that the browser calls a specified function to update an animation before the next repaint. The method takes a callback as an argument to be invoked before the repaint.


2 Answers

The delay that you configure for setTimeout and setInterval should never be thought of as an exact delay time. They represent the "minimum" amount of time that you'll wait before the function is executed. This is because the user-agent places the callback into the event queue when the time has elapsed, but if the user-agent is still working on some other task, the callback will sit there.

You should also know that there is a built-in absolute minimum time that you are never going to be able to go under of roughly 9-14ms. This is due to the internals of the user-agent.

like image 133
Scott Marcus Avatar answered Sep 24 '22 05:09

Scott Marcus


I've investigated almost any React Native solution for playing audio and various approaches of using javascript setTimeout()/setInterval(), but none of them were satisfactory in terms of time stability and accuracy.

Probably the only way to go at the moment is to glue some native module like this: https://developer.apple.com/library/content/samplecode/HelloMetronome/Introduction/Intro.html to js side, as described in RN Docs: https://facebook.github.io/react-native/docs/native-modules-ios.html, which gives a pretty decent result, but unfortunately, it's iOS only, of course.

like image 45
khrykin Avatar answered Sep 23 '22 05:09

khrykin