mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Split up createTimer into two methods, createTimer and createAndMaybeCallTimer
Summary: This diff splits up the current `createTimer` method (which is used for setTimeout, setInterval, etc.) into two methods, `createTimer` and `createAndMaybeCallTimer`. The latter is what's used by the existing Timing native module, and it preserves the existing behavior of this function. What's the difference? The current implementation of createTimer makes some assumptions about how it's called - namely, that it's called from JS asynchronously (using the bridge). Right now when you create a timer from JS, the JSTimers module passes in the timestamp for when the timer was created; in the native `createTimer`, we compare this timestamp to the current time, and if we find the timer has already expired, we immediately invoke the callback. Presumably this is done because we don't know how much time has elapsed since when the timer was scheduled in JS, and we want to make sure that it's called as soon as possible. Of course, this also means that `setTimeout(0)` will be immediately invoked, too, without waiting for the next frame. This all sounds fine, until we take a look at immediates. Immediates are currently implemented entirely in JS, and are called by the JS bridge; before returning control to native, we flush the immediates queue. This means that the current behavior is: 1) `setImmediate()` is always invoked before `setTimeout(0)`; 2) `setTimeout(0)` is invoked as soon as possible, before the next frame. However, this changes with bridgeless RN. With bridgeless RN, the native module methods are being replaced by C++ host functions, which are called synchronously. So if we keep the current logic in JavaTimerManager (where it checks if the timer has already expired), then `setTimeout(0)` will be invoked **before** immediates are called. So the change that I'm making for bridgeless RN is to always wait until the next frame before calling timers. This preserves the order of immediates/timers, although it does mean that `setTimeout(0)` will no longer be called as soon as possible. Of the two options, this seems preferable. Reviewed By: PeteTheHeat Differential Revision: D17403144 fbshipit-source-id: 8230f6ebe56aa20bfcf2325177c7812bc8e9c2ec
This commit is contained in:
committed by
Facebook Github Bot
parent
d67c8d4dec
commit
f054928124
@@ -278,7 +278,33 @@ public class JavaTimerManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void createTimer(
|
||||
/**
|
||||
* A method to be used for synchronously creating a timer. The timer will not be invoked until the
|
||||
* next frame, regardless of whether it has already expired (i.e. the delay is 0).
|
||||
*
|
||||
* @param callbackID An identifier for the callback that can be passed to JS or C++ to invoke it.
|
||||
* @param delay The time in ms before the callback should be invoked.
|
||||
* @param repeat Whether the timer should be repeated (used for setInterval).
|
||||
*/
|
||||
public void createTimer(final int callbackID, final long delay, final boolean repeat) {
|
||||
long initialTargetTime = SystemClock.nanoTime() / 1000000 + delay;
|
||||
Timer timer = new Timer(callbackID, initialTargetTime, (int) delay, repeat);
|
||||
synchronized (mTimerGuard) {
|
||||
mTimers.add(timer);
|
||||
mTimerIdsToTimers.put(callbackID, timer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A method to be used for asynchronously creating a timer. If the timer has already expired,
|
||||
* (based on the provided jsSchedulingTime) then it will be immediately invoked.
|
||||
*
|
||||
* @param callbackID An identifier that can be passed back to JS to invoke the callback.
|
||||
* @param duration The time in ms before the callback should be invoked.
|
||||
* @param jsSchedulingTime The time (ms since epoch) when this timer was created in JS.
|
||||
* @param repeat Whether the timer should be repeated (used for setInterval)
|
||||
*/
|
||||
public void createAndMaybeCallTimer(
|
||||
final int callbackID,
|
||||
final int duration,
|
||||
final double jsSchedulingTime,
|
||||
@@ -307,12 +333,7 @@ public class JavaTimerManager {
|
||||
return;
|
||||
}
|
||||
|
||||
long initialTargetTime = SystemClock.nanoTime() / 1000000 + adjustedDuration;
|
||||
Timer timer = new Timer(callbackID, initialTargetTime, duration, repeat);
|
||||
synchronized (mTimerGuard) {
|
||||
mTimers.add(timer);
|
||||
mTimerIdsToTimers.put(callbackID, timer);
|
||||
}
|
||||
createTimer(callbackID, adjustedDuration, repeat);
|
||||
}
|
||||
|
||||
public void deleteTimer(int timerId) {
|
||||
|
||||
@@ -72,7 +72,7 @@ public final class TimingModule extends ReactContextBaseJavaModule
|
||||
final int duration,
|
||||
final double jsSchedulingTime,
|
||||
final boolean repeat) {
|
||||
mJavaTimerManager.createTimer(callbackID, duration, jsSchedulingTime, repeat);
|
||||
mJavaTimerManager.createAndMaybeCallTimer(callbackID, duration, jsSchedulingTime, repeat);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
|
||||
Reference in New Issue
Block a user