Hi everyone, I'm Kasong.
React
recent years has been the perfect concurrent mode mainly consists of two parts:
- Interruptible update architecture based on
fiber
- Priority scheduling based on scheduler
It can be said that from the restructuring of fiber
React18
release of the official version of 06153cfbac4913 at the end of this year (or early next year) React
team was carried out around these two points.
If I tell you now that priority scheduling React
painstakingly for many years is natively supported by the browser, wouldn’t you be surprised?
The article refers to Building a Faster Web Experience with the postTask Scheduler .
What is priority scheduling
Suppose, we have a logging script that needs to be executed after the page is initialized:
initCriticalTracking();
The call stack torch diagram is as follows:
It can be seen that this is a long task that has been executed for 249.08ms, and the browser will drop frames during execution (shown as browser freeze).
Now, we wrap it in the callback function of priority scheduling function scheduler.postTask
scheduler.postTask(() => initCriticalTracking());
The long task is broken down into multiple short tasks:
The browser has the opportunity to rearrange and redraw between each task, reducing the possibility of dropped frames.
This disassembles tasks according to task priority and allocates execution time to the technology , which is priority scheduling .
scheduler.postTask is Chrome
achieved priority scheduling API .
scheduler.postTask is an experimental feature, you need to open #enable-experimental-web-platform-features in chrome://flags
How to implement priority scheduling before
scheduler.postTask
, which is usually called at different stages using the 16153cfbac4adb provided by the browser, was used to simulate priority scheduling , such as:
requestAnimationFrame
(abbreviated asrAF
) is generally used to process animation and will be triggered before the browser is renderedrequestIdleCallback
(abbreviated asrIC
) is called in idle time when there is no other task in each framesetTimeout
,postMessage
,MessageChannel
trigger between renderings
React
uses MessageChannel
implement priority scheduling, and setTimeout
as the downgrading scheme.
However, these API
all have their own jobs after all. Using their priority scheduling relatively rough.
For this reason, postTask Scheduler
born.
Use of postTask Scheduler
scheduler.postTask
has 3 optional priority levels:
priority | describe | polyfill implementation |
---|---|---|
user-blocking | Highest priority, may block user interaction | Use MessageChannel to schedule tasks, setTimeout as a downgrade scheme |
user-visible | The second priority is visible to users, but does not block user interaction. For example: rendering the content of the second screen. This is the default priority | Controlled by priority queue based on user-blocking implementation |
background | Lowest priority, usually perform non-urgent tasks, such as logging | Use rIC implementation, setTimeout(0) as a downgrade scheme |
The usage is very simple. The callback function registered in the following way will be default priority of :
// 默认优先级
scheduler.postTask(() => console.log('Hello, postTask'));
You can also specify the priority and execution delay:
// 调用后延迟1秒执行,优先级最低
scheduler.postTask(() => console.log('Hello, postTask'), {
delay: 1000,
priority: 'background',
});
postTask
built on AbortSignal API , so we can cancel callback functions that are still in the queue and have not been executed.
By using TaskController API
control:
const controller = new TaskController('background');
window.addEventListener('beforeunload', () => controller.abort());
scheduler.postTask(() => console.log('Hello, postTask'), {
signal: controller.signal,
});
At the same time, the experimental schedule.wait
method allows us to easily wait for a certain time before performing the task.
For example, we can asynchronously load xxx.js
after the page is loaded:
async function loadxxx() {
// 等待事件被派发
await scheduler.wait('myPageHasLoaded');
return import('xxx.js');
}
// 页面加载后派发事件
window.dispatchEvent(new CustomEvent('myPageHasLoaded'));
The above code is simplified postTask
of event
configuration items:
scheduler.postTask(() => import('xxx.js'), {
event: 'myPageHasLoaded'
})
Summarize
priority scheduling can be applied in many fields, such as:
- Resource advance and postponement request
- Lazy loading of third-party resources
......
It is foreseeable that this will inevitably increase the complexity of front-end programming in the future.
Just as before, when the web
complicated to a certain extent, a front-end framework appeared, and developers did not need to directly operate DOM
.
In the future, when the priority scheduling complicated to a certain extent, an integrated solution will surely appear, so that developers do not need to directly manipulate the priority.
React
minute, isn't this what 06153cfbac4f1d is doing now?
Welcome to join the human high-quality front-end framework research group , lead the flight
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。