成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

100行代碼實現React核心調度功能

開發 前端
想必大家都知道React有一套基于Fiber架構的調度系統,本文會用100行代碼實現這套調度系統,讓你快速了解React的調度原理。

[[440697]]

大家好,我卡頌。

想必大家都知道React有一套基于Fiber架構的調度系統。這套調度系統的基本功能包括:

  • 更新有不同優先級
  • 一次更新可能涉及多個組件的render,這些render可能分配到多個宏任務中執行(即時間切片)
  • 高優先級更新會打斷進行中的低優先級更新

本文會用100行代碼實現這套調度系統,讓你快速了解React的調度原理。

我知道你不喜歡看大段的代碼,所以本文會以圖+代碼片段的形式講解。

文末有完整的在線Demo,你可以自己上手玩玩。

開整!

準備工作

我們用work這一數據結構代表一份工作,work.count代表這份工作要重復做某件事的次數。

在Demo中要重復做的事是“執行insertItem方法,向頁面插入”:

  1. const insertItem = (content: string) => { 
  2.   const ele = document.createElement('span'); 
  3.   ele.innerText = `${content}`; 
  4.   contentBox.appendChild(ele); 
  5. }; 

所以,對于如下work:

  1. const work1 = { 
  2.   count: 100 

代表:執行100次insertItem向頁面插入100個。

work可以類比React的一次更新,work.count類比這次更新要render的組件數量。所以Demo是對React更新流程的類比

來實現第一版的調度系統,流程如圖:

包括三步:

  1. 向workList隊列(用于保存所有work)插入work
  2. schedule方法從workList中取出work,傳遞給perform
  3. perform方法執行完work的所有工作后重復步驟2

代碼如下:

  1. // 保存所有work的隊列 
  2. const workList: work[] = []; 
  3.  
  4. // 調度 
  5. function schedule() { 
  6.   // 從隊列尾取一個work 
  7.   const curWork = workList.pop(); 
  8.    
  9.   if (curWork) { 
  10.     perform(curWork); 
  11.   } 
  12.  
  13. // 執行 
  14. function perform(workWork) { 
  15.   while (work.count) { 
  16.     work.count--; 
  17.     insertItem(); 
  18.   } 
  19.   schedule(); 

為按鈕綁定點擊交互,最基本的調度系統就完成了:

  1. button.onclick = () => { 
  2.   workList.unshift({ 
  3.     count: 100 
  4.   }) 
  5.   schedule(); 

點擊button就能插入100個。

用React類比就是:點擊button,觸發同步更新,100個組件render

接下來我們將其改造成異步的。

Scheduler

React內部使用Scheduler完成異步調度。

Scheduler是獨立的包。所以可以用他改造我們的Demo。

Scheduler預置了5種優先級,從上往下優先級降低:

  • ImmediatePriority,最高的同步優先級
  • UserBlockingPriority
  • NormalPriority
  • LowPriority
  • IdlePriority,最低優先級

scheduleCallback方法接收優先級與回調函數fn,用于調度fn:

  1. // 將回調函數fn以LowPriority優先級調度 
  2. scheduleCallback(LowPriority, fn) 

在Scheduler內部,執行scheduleCallback后會生成task這一數據結構:

  1. const task1 = { 
  2.   expiration: startTime + timeout, 
  3.   callback: fn 

task1.expiration代表task1的過期時間,Scheduler會優先執行過期的task.callback。

expiration中startTime為當前開始時間,不同優先級的timeout不同。

比如,ImmediatePriority的timeout為-1,由于:

  1. startTime - 1 < startTime 

所以ImmediatePriority會立刻過期,callback立刻執行。

而IdlePriority對應timeout為1073741823(最大的31位帶符號整型),其callback需要非常長時間才會執行。

callback會在新的宏任務中執行,這就是Scheduler調度的原理。

用Scheduler改造Demo

改造后的流程如圖:

改造前,work直接從workList隊列尾取出:

  1. // 改造前 
  2. const curWork = workList.pop(); 

改造后,work可以擁有不同優先級,通過priority字段表示。

比如,如下work代表「以NormalPriority優先級插入100個」:

  1. const work1 = { 
  2.   count: 100, 
  3.   priority: NormalPriority 

改造后每次都使用最高優先級的work:

  1. // 改造后 
  2. // 對workList排序后取priority值最小的(值越小,優先級越高) 
  3. const curWork = workList.sort((w1, w2) => { 
  4.    return w1.priority - w2.priority; 
  5. })[0]; 

改造后流程的變化

由流程圖可知,Scheduler不再直接執行perform,而是通過執行scheduleCallback調度perform.bind(null, work)。

即,滿足一定條件的情況下,生成新task:

  1. const someTask = { 
  2.   callback: perform.bind(nullwork), 
  3.   expiration: xxx 

同時,work的工作也是可中斷的。在改造前,perform會同步執行完work中的所有工作:

  1. while (work.count) { 
  2.   work.count--; 
  3.   insertItem(); 

改造后,work的執行流程隨時可能中斷:

  1. while (!needYield() && work.count) { 
  2.   work.count--; 
  3.   insertItem(); 

needYield方法的實現(何時會中斷)請參考文末在線Demo

高優先級打斷低優先級的例子

舉例來看一個高優先級打斷低優先級的例子:

插入一個低優先級work,屬性如下

  1. const work1 = { 
  2.   count: 100, 
  3.   priority: LowPriority 

經歷schedule(調度),perform(執行),在執行了80次工作時,突然插入一個高優先級work,此時:

  1. const work1 = { 
  2.   // work1已經執行了80次工作,還差20次執行完 
  3.   count: 20, 
  4.   priority: LowPriority 
  5. // 新插入的高優先級work 
  6. const work2 = { 
  7.   count: 100, 
  8.   priority: ImmediatePriority 

work1工作中斷,繼續schedule。由于work2優先級更高,會進入work2對應perform,執行100次工作

work2執行完后,繼續schedule,執行work1剩余的20次工作

在這個例子中,我們需要區分2個「打斷」的概念:

在步驟3中,work1執行的工作被打斷。這是微觀角度的「打斷」

由于work1被打斷,所以繼續schedule。下一個執行工作的是更高優的work2。work2的到來導致work1被打斷,這是宏觀角度的「打斷」

之所以要區分「宏/微觀」,是因為「微觀的打斷」不一定意味著「宏觀的打斷」。

比如:work1由于時間切片用盡,被打斷。沒有其他更高優的work與他競爭schedule的話,下一次perform還是work1。

這種情況下微觀下多次打斷,但是宏觀來看,還是同一個work在執行。這就是「時間切片」的原理。

調度系統的實現原理

以下是調度系統的完整實現原理:

對照流程圖來看:

總結

本文是React調度系統的簡易實現,主要包括兩個階段:

  • schedule
  • perform

如果你對代碼的具體實現感興趣,下面是完整Demo地址。

參考資料

[1]Scheduler:

https://github.com/facebook/react/tree/main/packages/scheduler

[2]完整Demo地址:

https://codesandbox.io/s/xenodochial-alex-db74g?file=/src/index.ts

 

責任編輯:姜華 來源: 魔術師卡頌
相關推薦

2022-04-15 08:07:21

ReactDiff算法

2023-07-03 07:51:47

2021-12-26 12:10:21

React組件前端

2024-08-01 08:45:17

2022-02-08 12:30:30

React事件系統React事件系統

2021-10-27 06:55:18

ReacFiber架構

2020-08-21 13:40:17

Python代碼人體膚色

2023-11-27 07:10:06

日志中間件

2015-02-09 10:43:00

JavaScript

2022-03-14 09:57:30

Python代碼

2017-03-28 21:03:35

代碼React.js

2023-05-04 07:34:37

Rust代碼CPU

2025-05-22 07:40:32

2022-07-07 15:50:19

Python開發功能

2020-04-10 12:25:28

Python爬蟲代碼

2017-02-08 14:16:17

C代碼終端

2022-04-12 08:09:22

Nodejs前端面試題

2018-02-08 16:45:22

前端JS粘貼板

2018-01-10 22:19:44

2019-11-15 15:50:41

JS代碼React前端
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美色综合| 亚洲 欧美 另类 综合 偷拍 | 亚洲成人免费视频在线观看 | 一区二区三区四区在线免费观看 | 色吧色综合 | 国产精品日韩欧美一区二区三区 | 国产一区二区三区免费 | 国产成人网 | 男女爱爱福利视频 | 色视频在线播放 | 国精品一区 | 久久久性色精品国产免费观看 | 性色av一区二区三区 | 久久久久国色av免费观看性色 | 综合精品 | 一色一黄视频 | 国产精品一区二 | 中文字幕免费观看 | av播播| 久久国产一区二区 | 亚洲免费精品 | 亚洲精品一区二三区不卡 | 国产欧美视频一区二区 | av中文字幕在线观看 | 国产一区精品在线 | 97国产一区二区 | 色综合色综合网色综合 | 亚洲精品第一 | 午夜丰满少妇一级毛片 | 亚洲综合视频 | 午夜电影日韩 | 青青草一区二区 | 成人免费观看视频 | 国产精品久久视频 | 国产ts人妖一区二区三区 | 欧美激情亚洲激情 | av免费网站在线 | 亚洲看片网站 | 日日操操 | 91看片官网 | 在线视频一区二区三区 |