Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leverage scheduler.yield in splitTask when available #66001

Merged
merged 9 commits into from
Oct 16, 2024
26 changes: 20 additions & 6 deletions packages/interactivity/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ interface Flusher {
readonly dispose: () => void;
}

declare global {
interface Window {
scheduler: {
readonly yield: () => void;
westonruter marked this conversation as resolved.
Show resolved Hide resolved
};
}
}

/**
* Executes a callback function after the next frame is rendered.
*
Expand All @@ -48,12 +56,18 @@ const afterNextFrame = ( callback: () => void ) => {
*
* @return Promise
*/
export const splitTask = () => {
return new Promise( ( resolve ) => {
// TODO: Use scheduler.yield() when available.
setTimeout( resolve, 0 );
} );
};
export const splitTask =
'scheduler' in window &&
westonruter marked this conversation as resolved.
Show resolved Hide resolved
typeof window.scheduler === 'object' &&
null !== window.scheduler &&
'yield' in window.scheduler &&
typeof window.scheduler.yield === 'function'
? window.scheduler.yield.bind( window.scheduler )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other places in Gutenberg, I believe we use requestIdleCallback to optimize for UI responsiveness and delay some tasks with lower priority. I wonder if you can speak about the difference and when to favor one over the other.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With requestIdleCallback the idleness may occur several seconds after requested which would not be desirable for hydration. For splitTask it's purely to break up long tasks which remain high priority. So both have their use cases.

: () => {
return new Promise( ( resolve ) => {
setTimeout( resolve, 0 );
} );
};

/**
* Creates a Flusher object that can be used to flush computed values and notify listeners.
Expand Down
Loading