Files
react/packages/react-native-renderer/src/ReactNativeFrameScheduling.js
T
Andrew Clark 9b36df86c6 Use requestIdleCallback timeout to force expiration (#11548)
* Don't call idle callback unless there's time remaining

* Expiration fixture

Fixture that demonstrates how async work expires after a certain interval.
The fixture clogs the main thread with animation work, so it only works if the
`timeout` option is provided to `requestIdleCallback`.

* Pass timeout option to requestIdleCallback

Forces `requestIdleCallback` to fire if too much time has elapsed, even if the
main thread is busy. Required to make expiration times work properly. Otherwise,
async work can expire, but React never has a chance to flush it because the
browser never calls into React.
2017-11-15 13:46:17 -08:00

57 lines
1.7 KiB
JavaScript

/**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import type {Deadline} from 'react-reconciler';
const hasNativePerformanceNow =
typeof performance === 'object' && typeof performance.now === 'function';
const now = hasNativePerformanceNow
? () => performance.now()
: () => Date.now();
type Callback = (deadline: Deadline) => void;
let scheduledCallback: Callback | null = null;
let frameDeadline: number = 0;
const frameDeadlineObject: Deadline = {
timeRemaining: () => frameDeadline - now(),
};
function setTimeoutCallback() {
// TODO (bvaughn) Hard-coded 5ms unblocks initial async testing.
// React API probably changing to boolean rather than time remaining.
// Longer-term plan is to rewrite this using shared memory,
// And just return the value of the bit as the boolean.
frameDeadline = now() + 5;
const callback = scheduledCallback;
scheduledCallback = null;
if (callback !== null) {
callback(frameDeadlineObject);
}
}
// RN has a poor polyfill for requestIdleCallback so we aren't using it.
// This implementation is only intended for short-term use anyway.
// We also don't implement cancel functionality b'c Fiber doesn't currently need it.
function scheduleDeferredCallback(callback: Callback): number {
// We assume only one callback is scheduled at a time b'c that's how Fiber works.
scheduledCallback = callback;
return setTimeout(setTimeoutCallback, 1);
}
function cancelDeferredCallback(callbackID: number) {
scheduledCallback = null;
clearTimeout(callbackID);
}
export {now, scheduleDeferredCallback, cancelDeferredCallback};