astoilkov / main-thread-scheduling Goto Github PK
View Code? Open in Web Editor NEWFast and consistently responsive apps using a single function call
License: MIT License
Fast and consistently responsive apps using a single function call
License: MIT License
I'm currently using a conditional to opt out on the server. But it would be less risky if on node it just performs a pass through.
I've also had some problems with jest clear timers getting stuck in a infinite loop if MTS is used on one of those unit tested components
It could be useful if node_env is set to test, do something like resolve a promise with a setTimeout. This may also help with other things like some of my tests "fail" because X function I'm spying on wasn't called fast enough.
Ive been wanting to use main thread scheduling to time aggressive updates on a function.
So in this case, if i have a update come through, then 1ms later another update is sent, id want to cancel the preexisting scheduled event and reschedule only the last valid call.
I do something like this with idleCallback but was wondering if this library could expose something similar, perhaps a label?
So if "something" already exists, and a new "something" event is sent in, remove the previous one from the queue and push this onto the end instead
class RenderWhenIdle extends React.Component {
constructor() {
super();
this.updateDebounced = this.updateDebounced.bind(this);
this.idleCallback = null;
}
updateDebounced() {
this.idleCallback = requestIdleCallback(() => {
this.forceUpdate();
}, { timeout: 200 });
}
shouldComponentUpdate(nextProps) {
if (this.idleCallback) { cancelIdleCallback(this.idleCallback); }
this.updateDebounced();
return false;
}
componentWillUnmount() {
cancelIdleCallback(this.idleCallback);
}
componentDidMount() {
this.updateDebounced();
}
render() {
return this.props.children;
}
}
The performance overhead of the current Promise based API is not non-trivial. Any chance to get a callback API as well?
Hey no came across this article and though this would be a brilliant addition to your work.
Have any opinion on if or how this could fit into your project?
If I use a .then() chain, I believe the browser is able to GC better compared to async await which I believe prevents automated GC
Have you come across this scenario before?
Hi! π
Firstly, thanks for your work on this project! π
Today I used patch-package to patch [email protected]
for the project I'm working on.
Here is the diff that solved my problem:
diff --git a/node_modules/main-thread-scheduling/src/isTimeToYield.ts b/node_modules/main-thread-scheduling/src/isTimeToYield.ts
index f54e6a9..d827ae9 100644
--- a/node_modules/main-thread-scheduling/src/isTimeToYield.ts
+++ b/node_modules/main-thread-scheduling/src/isTimeToYield.ts
@@ -19,8 +19,10 @@ export default function isTimeToYield(priority: 'background' | 'user-visible'):
}
lastCallTime = now
+ // @ts-ignore: scheduling is new experimental API
+ const inputPending = navigator.scheduling?.isInputPending?.()
lastResult =
- now >= calculateDeadline(priority) || navigator.scheduling?.isInputPending?.() === true
+ now >= calculateDeadline(priority) || inputPending === true
if (lastResult) {
state.frameTimeElapsed = true
diff --git a/node_modules/main-thread-scheduling/src/tracking.ts b/node_modules/main-thread-scheduling/src/tracking.ts
index 033c536..14cf024 100644
--- a/node_modules/main-thread-scheduling/src/tracking.ts
+++ b/node_modules/main-thread-scheduling/src/tracking.ts
@@ -41,6 +41,7 @@ export function startTracking(): void {
isTracking = false
if (typeof cancelIdleCallback !== 'undefined') {
+ // @ts-ignore: will be defined
cancelIdleCallback(idleCallbackId)
}
} else {
diff --git a/node_modules/main-thread-scheduling/src/yieldControl.ts b/node_modules/main-thread-scheduling/src/yieldControl.ts
index 7236816..74a98b2 100644
--- a/node_modules/main-thread-scheduling/src/yieldControl.ts
+++ b/node_modules/main-thread-scheduling/src/yieldControl.ts
@@ -49,6 +49,7 @@ async function schedule(priority: 'user-visible' | 'background'): Promise<void>
await new Promise<void>((resolve) => requestNextTask(resolve))
// istanbul ignore if
+ // @ts-ignore: scheduling is new experimental API
if (navigator.scheduling?.isInputPending?.() === true) {
await schedule(priority)
} else if (state.frameWorkStartTime === undefined) {
This issue body was partially generated by patch-package.
Since this is a client side library, is it possible to publish a single .js file which exposes this functionality and allows for general purpose importing, without having to build a Node.js project for it?
Can it be used in vue οΌ
This is a cool idea for the future of web-apps, and it's nice to have a userland implementation before it's added to the standard! Since you said in the README to make an issue if there's an alternate solution to UI freezing, I'm making this issue to mention my package isoworker
, which does some magic to make web workers easier to use. Most worker wrappers that allow you to avoid creating workers by hand have one key flaw: you can't easily copy anything from the main thread into the worker and must send over only a function. My package mitigates pretty much all the complexity of web workers: you can make long-running closures on a separate thread with virtually no restrictions, it almost works like calling the closure asynchronously on the main thread.
This package still seems better for cases where there is a lot of data being processed or constant communication is necessary, but isoworker
can yield zero UI freezing by running on a separate thread.
Currently, I have added only two priorities to the library β background
and user-visible
. I feel this won't be enough. However, I can't imagine all the use cases the library will be used in. This is why I am starting a discussion here, so together, we can find the right priorities.
This project is great, I would like to ask whether it can interrupt the rendering of react. For example, if there is a list of 10,000 length arrays and react updates this array when performing state updates, can it interrupt the rendering
Hi and thanks for your work on this library !
Since version 11.0.0 (i.e. with versions 11.0.0 and 12.0.0) I have encountered problems when I compile a project with Vite (5.0.x) that uses "main-thread-scheduling".
The compilation fails with the following message and Vite stops :
β [ERROR] Could not resolve "./src/utils/queueTask"
node_modules/main-thread-scheduling/index.js:7:37:
7 β export { default as queueTask } from './src/utils/queueTask';
β΅ ~~~~~~~~~~~~~~~~~~~~~~~
β [ERROR] Could not resolve "./src/utils/withResolvers"
node_modules/main-thread-scheduling/index.js:8:41:
8 β export { default as withResolvers } from './src/utils/withResolvers';
β΅ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
β [ERROR] Could not resolve "./src/utils/requestAfterFrame"
node_modules/main-thread-scheduling/index.js:9:38:
9 β export { default as afterFrame } from './src/utils/requestAfterFrame';
β΅ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
β [ERROR] Could not resolve "./utils/hasValidContext"
node_modules/main-thread-scheduling/src/isTimeToYield.js:2:28:
2 β import hasValidContext from './utils/hasValidContext';
β΅ ~~~~~~~~~~~~~~~~~~~~~~~~~
β [ERROR] Could not resolve "./utils/queueTask"
node_modules/main-thread-scheduling/src/yieldControl.js:2:22:
2 β import queueTask from './utils/queueTask';
β΅ ~~~~~~~~~~~~~~~~~~~
β [ERROR] Could not resolve "./utils/hasValidContext"
node_modules/main-thread-scheduling/src/yieldControl.js:4:28:
4 β import hasValidContext from './utils/hasValidContext';
β΅ ~~~~~~~~~~~~~~~~~~~~~~~~~
β [ERROR] Could not resolve "./utils/promiseEscape"
node_modules/main-thread-scheduling/src/yieldControl.js:5:58:
5 β ...PromiseEscape, requestPromiseEscape } from './utils/promiseEscape';
β΅ ~~~~~~~~~~~~~~~~~~~~~~~
β [ERROR] Could not resolve "./tasks/createTask"
node_modules/main-thread-scheduling/src/yieldControl.js:6:23:
6 β import createTask from './tasks/createTask';
β΅ ~~~~~~~~~~~~~~~~~~~~
β [ERROR] Could not resolve "./tasks/removeTask"
node_modules/main-thread-scheduling/src/yieldControl.js:7:23:
7 β import removeTask from './tasks/removeTask';
β΅ ~~~~~~~~~~~~~~~~~~~~
β [ERROR] Could not resolve "./tasks/nextTask"
node_modules/main-thread-scheduling/src/yieldControl.js:8:25:
8 β import { nextTask } from './tasks/nextTask';
β΅ ~~~~~~~~~~~~~~~~~~
β [ERROR] Could not resolve "./utils/withResolvers"
node_modules/main-thread-scheduling/src/schedulingState.js:1:26:
1 β import withResolvers from './utils/withResolvers';
β΅ ~~~~~~~~~~~~~~~~~~~~~~~
Error: Build failed with 11 errors:
node_modules/main-thread-scheduling/index.js:7:37: ERROR: Could not resolve "./src/utils/queueTask"
node_modules/main-thread-scheduling/index.js:8:41: ERROR: Could not resolve "./src/utils/withResolvers"
node_modules/main-thread-scheduling/index.js:9:38: ERROR: Could not resolve "./src/utils/requestAfterFrame"
node_modules/main-thread-scheduling/src/isTimeToYield.js:2:28: ERROR: Could not resolve "./utils/hasValidContext"
node_modules/main-thread-scheduling/src/schedulingState.js:1:26: ERROR: Could not resolve "./utils/withResolvers"
...
at failureErrorWithLog (/home/projects/vitejs-vite-adh7q9/node_modules/esbuild/lib/main.js:1641:15)
at eval (/home/projects/vitejs-vite-adh7q9/node_modules/esbuild/lib/main.js:1049:25)
at eval (/home/projects/vitejs-vite-adh7q9/node_modules/esbuild/lib/main.js:1517:9) {
errors: [Getter/Setter],
warnings: [Getter/Setter]
}
It happens in a large project I'm working on but you can see a minimal repro here in a projet with only Vite
, Typescript
and main-thread-scheduling
(this is a stackblitz project, hope this is fine to demonstrate the issue - try to change the main-thread-scheduling
version to 10.0.0 in package.json
to see it was working fine with older versions).
Am I doing something wrong or is there a workaround ?
Thanks !
I'll like to see a comparison between this library and other approaches followed by some frameworks, like react or solid.js (the latter being a simplified version of the former).
I know that solid for example doesn't have different priorities for its scheduler, I'll like to know how much it benefits to do the distinction between 'user-visible' and 'background' in your approach.
I have entered the link, this CodeSandbox, can't find any difference between un-commented and commented code..Maybe my PC is powerful enought to handle the heavy task...Do u want to use some tools to test your improvements, such as tinybench?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.